Migrate dataSourceSrv to getDataSourceSrv

This commit is contained in:
Alexander Zobnin
2020-03-23 16:05:31 +03:00
parent dad0fd965d
commit 2761b4d966
11 changed files with 84 additions and 63 deletions

View File

@@ -1,4 +1,5 @@
import _ from 'lodash'; import _ from 'lodash';
import { getDataSourceSrv } from '@grafana/runtime';
import { migrateDSConfig } from './migrations'; import { migrateDSConfig } from './migrations';
const SUPPORTED_SQL_DS = ['mysql', 'postgres', 'influxdb']; const SUPPORTED_SQL_DS = ['mysql', 'postgres', 'influxdb'];
@@ -23,9 +24,7 @@ const defaultConfig = {
export class ZabbixDSConfigController { export class ZabbixDSConfigController {
/** @ngInject */ /** @ngInject */
constructor($scope, $injector, datasourceSrv) { constructor() {
this.datasourceSrv = datasourceSrv;
this.current.jsonData = migrateDSConfig(this.current.jsonData); this.current.jsonData = migrateDSConfig(this.current.jsonData);
_.defaults(this.current.jsonData, defaultConfig); _.defaults(this.current.jsonData, defaultConfig);
@@ -39,7 +38,7 @@ export class ZabbixDSConfigController {
} }
getSupportedDBDataSources() { getSupportedDBDataSources() {
let datasources = this.datasourceSrv.getAll(); let datasources = getDataSourceSrv().getAll();
return _.filter(datasources, ds => { return _.filter(datasources, ds => {
return _.includes(SUPPORTED_SQL_DS, ds.type); return _.includes(SUPPORTED_SQL_DS, ds.type);
}); });
@@ -53,7 +52,7 @@ export class ZabbixDSConfigController {
loadCurrentDBDatasource() { loadCurrentDBDatasource() {
const dsName= this.current.jsonData.dbConnectionDatasourceName; const dsName= this.current.jsonData.dbConnectionDatasourceName;
this.datasourceSrv.loadDatasource(dsName) getDataSourceSrv().loadDatasource(dsName)
.then(ds => { .then(ds => {
if (ds) { if (ds) {
this.dbConnectionDatasourceId = ds.id; this.dbConnectionDatasourceId = ds.id;
@@ -66,7 +65,7 @@ export class ZabbixDSConfigController {
return; return;
} }
this.datasourceSrv.loadDatasource(this.current.name) getDataSourceSrv().loadDatasource(this.current.name)
.then(ds => { .then(ds => {
return ds.getVersion(); return ds.getVersion();
}) })

View File

@@ -16,7 +16,7 @@ const DEFAULT_ZABBIX_VERSION = 3;
export class ZabbixDatasource { export class ZabbixDatasource {
/** @ngInject */ /** @ngInject */
constructor(instanceSettings, templateSrv, datasourceSrv, zabbixAlertingSrv) { constructor(instanceSettings, templateSrv, zabbixAlertingSrv) {
this.templateSrv = templateSrv; this.templateSrv = templateSrv;
this.zabbixAlertingSrv = zabbixAlertingSrv; this.zabbixAlertingSrv = zabbixAlertingSrv;
@@ -75,7 +75,7 @@ export class ZabbixDatasource {
dbConnectionRetentionPolicy: this.dbConnectionRetentionPolicy, dbConnectionRetentionPolicy: this.dbConnectionRetentionPolicy,
}; };
this.zabbix = new Zabbix(zabbixOptions, datasourceSrv); this.zabbix = new Zabbix(zabbixOptions);
} }
//////////////////////// ////////////////////////

View File

@@ -1,11 +1,17 @@
import mocks from '../../test-setup/mocks';
import { DBConnector } from '../zabbix/connectors/dbConnector'; 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', () => { describe('DBConnector', () => {
let ctx = {}; const ctx: any = {};
const datasourceSrv = mocks.datasourceSrvMock;
datasourceSrv.loadDatasource.mockResolvedValue({ id: 42, name: 'foo', meta: {} });
datasourceSrv.getAll.mockReturnValue([{ id: 42, name: 'foo' }]);
describe('When init DB connector', () => { describe('When init DB connector', () => {
beforeEach(() => { beforeEach(() => {
@@ -13,34 +19,34 @@ describe('DBConnector', () => {
datasourceId: 42, datasourceId: 42,
datasourceName: undefined datasourceName: undefined
}; };
loadDatasourceMock.mockClear();
getAllMock.mockClear();
}); });
it('should try to load datasource by name first', () => { it('should try to load datasource by name first', () => {
ctx.options = { const dbConnector = new DBConnector({ datasourceName: 'bar' });
datasourceName: 'bar'
};
const dbConnector = new DBConnector(ctx.options, datasourceSrv);
dbConnector.loadDBDataSource(); dbConnector.loadDBDataSource();
expect(datasourceSrv.getAll).not.toHaveBeenCalled(); expect(getAllMock).not.toHaveBeenCalled();
expect(datasourceSrv.loadDatasource).toHaveBeenCalledWith('bar'); expect(loadDatasourceMock).toHaveBeenCalledWith('bar');
}); });
it('should load datasource by id if name not present', () => { 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(); dbConnector.loadDBDataSource();
expect(datasourceSrv.getAll).toHaveBeenCalled(); expect(getAllMock).toHaveBeenCalled();
expect(datasourceSrv.loadDatasource).toHaveBeenCalledWith('foo'); expect(loadDatasourceMock).toHaveBeenCalledWith('foo');
}); });
it('should throw error if no name and id specified', () => { it('should throw error if no name and id specified', () => {
ctx.options = {}; 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'); return expect(dbConnector.loadDBDataSource()).rejects.toBe('Data Source name should be specified');
}); });
it('should throw error if datasource with given id is not found', () => { it('should throw error if datasource with given id is not found', () => {
ctx.options.datasourceId = 45; 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'); return expect(dbConnector.loadDBDataSource()).rejects.toBe('Data Source with ID 45 not found');
}); });
}); });

View File

@@ -1,17 +1,20 @@
import { InfluxDBConnector } from '../zabbix/connectors/influxdb/influxdbConnector'; import { InfluxDBConnector } from '../zabbix/connectors/influxdb/influxdbConnector';
import { compactQuery } from '../utils'; import { compactQuery } from '../utils';
jest.mock('@grafana/runtime', () => ({
getDataSourceSrv: jest.fn(() => ({
loadDatasource: jest.fn().mockResolvedValue(
{ id: 42, name: 'InfluxDB DS', meta: {} }
),
})),
}));
describe('InfluxDBConnector', () => { describe('InfluxDBConnector', () => {
let ctx = {}; let ctx = {};
beforeEach(() => { beforeEach(() => {
ctx.options = { datasourceName: 'InfluxDB DS', retentionPolicy: 'longterm' }; ctx.options = { datasourceName: 'InfluxDB DS', retentionPolicy: 'longterm' };
ctx.datasourceSrvMock = { ctx.influxDBConnector = new InfluxDBConnector(ctx.options);
loadDatasource: jest.fn().mockResolvedValue(
{ id: 42, name: 'InfluxDB DS', meta: {} }
),
};
ctx.influxDBConnector = new InfluxDBConnector(ctx.options, ctx.datasourceSrvMock);
ctx.influxDBConnector.invokeInfluxDBQuery = jest.fn().mockResolvedValue([]); ctx.influxDBConnector.invokeInfluxDBQuery = jest.fn().mockResolvedValue([]);
ctx.defaultQueryParams = { ctx.defaultQueryParams = {
itemids: ['123', '234'], itemids: ['123', '234'],

View File

@@ -1,4 +1,5 @@
import _ from 'lodash'; import _ from 'lodash';
import { getDataSourceSrv } from '@grafana/runtime';
export const DEFAULT_QUERY_LIMIT = 10000; export const DEFAULT_QUERY_LIMIT = 10000;
export const HISTORY_TO_TABLE_MAP = { 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. * `testDataSource()` methods, which describe how to fetch data from source other than Zabbix API.
*/ */
export class DBConnector { export class DBConnector {
constructor(options, datasourceSrv) { constructor(options) {
this.datasourceSrv = datasourceSrv;
this.datasourceId = options.datasourceId; this.datasourceId = options.datasourceId;
this.datasourceName = options.datasourceName; this.datasourceName = options.datasourceName;
this.datasourceTypeId = null; this.datasourceTypeId = null;
this.datasourceTypeName = null; this.datasourceTypeName = null;
} }
static loadDatasource(dsId, dsName, datasourceSrv) { static loadDatasource(dsId, dsName) {
if (!dsName && dsId !== undefined) { if (!dsName && dsId !== undefined) {
let ds = _.find(datasourceSrv.getAll(), {'id': dsId}); let ds = _.find(getDataSourceSrv().getAll(), {'id': dsId});
if (!ds) { if (!ds) {
return Promise.reject(`Data Source with ID ${dsId} not found`); return Promise.reject(`Data Source with ID ${dsId} not found`);
} }
dsName = ds.name; dsName = ds.name;
} }
if (dsName) { if (dsName) {
return datasourceSrv.loadDatasource(dsName); return getDataSourceSrv().loadDatasource(dsName);
} else { } else {
return Promise.reject(`Data Source name should be specified`); return Promise.reject(`Data Source name should be specified`);
} }
} }
loadDBDataSource() { loadDBDataSource() {
return DBConnector.loadDatasource(this.datasourceId, this.datasourceName, this.datasourceSrv) return DBConnector.loadDatasource(this.datasourceId, this.datasourceName)
.then(ds => { .then(ds => {
this.datasourceTypeId = ds.meta.id; this.datasourceTypeId = ds.meta.id;
this.datasourceTypeName = ds.meta.name; this.datasourceTypeName = ds.meta.name;

View File

@@ -11,8 +11,8 @@ const consolidateByFunc = {
}; };
export class InfluxDBConnector extends DBConnector { export class InfluxDBConnector extends DBConnector {
constructor(options, datasourceSrv) { constructor(options) {
super(options, datasourceSrv); super(options);
this.retentionPolicy = options.retentionPolicy; this.retentionPolicy = options.retentionPolicy;
super.loadDBDataSource().then(ds => { super.loadDBDataSource().then(ds => {
this.influxDS = ds; this.influxDS = ds;

View File

@@ -11,8 +11,8 @@ const supportedDatabases = {
}; };
export class SQLConnector extends DBConnector { export class SQLConnector extends DBConnector {
constructor(options, datasourceSrv) { constructor(options) {
super(options, datasourceSrv); super(options);
this.limit = options.limit || DEFAULT_QUERY_LIMIT; this.limit = options.limit || DEFAULT_QUERY_LIMIT;
this.sqlDialect = null; this.sqlDialect = null;

View File

@@ -25,7 +25,7 @@ const REQUESTS_TO_BIND = [
]; ];
export class Zabbix { export class Zabbix {
constructor(options, datasourceSrv) { constructor(options) {
let { let {
url, url,
username, username,
@@ -57,7 +57,7 @@ export class Zabbix {
if (enableDirectDBConnection) { if (enableDirectDBConnection) {
const connectorOptions = { dbConnectionRetentionPolicy }; const connectorOptions = { dbConnectionRetentionPolicy };
this.initDBConnector(dbConnectionDatasourceId, dbConnectionDatasourceName, datasourceSrv, connectorOptions) this.initDBConnector(dbConnectionDatasourceId, dbConnectionDatasourceName, connectorOptions)
.then(() => { .then(() => {
this.getHistoryDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getHistory, 'getHistory', this.dbConnector); this.getHistoryDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getHistory, 'getHistory', this.dbConnector);
this.getTrendsDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getTrends, 'getTrends', 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) { initDBConnector(datasourceId, datasourceName, options) {
return DBConnector.loadDatasource(datasourceId, datasourceName, datasourceSrv) return DBConnector.loadDatasource(datasourceId, datasourceName)
.then(ds => { .then(ds => {
let connectorOptions = { datasourceId, datasourceName }; let connectorOptions = { datasourceId, datasourceName };
if (ds.type === 'influxdb') { if (ds.type === 'influxdb') {
connectorOptions.retentionPolicy = options.dbConnectionRetentionPolicy; connectorOptions.retentionPolicy = options.dbConnectionRetentionPolicy;
this.dbConnector = new InfluxDBConnector(connectorOptions, datasourceSrv); this.dbConnector = new InfluxDBConnector(connectorOptions);
} else { } else {
this.dbConnector = new SQLConnector(connectorOptions, datasourceSrv); this.dbConnector = new SQLConnector(connectorOptions);
} }
return this.dbConnector; return this.dbConnector;
}); });

View File

@@ -4,15 +4,20 @@ import {TriggerPanelCtrl} from '../triggers_panel_ctrl';
import {DEFAULT_TARGET, DEFAULT_SEVERITY, PANEL_DEFAULTS} from '../triggers_panel_ctrl'; import {DEFAULT_TARGET, DEFAULT_SEVERITY, PANEL_DEFAULTS} from '../triggers_panel_ctrl';
import {CURRENT_SCHEMA_VERSION} from '../migrations'; import {CURRENT_SCHEMA_VERSION} from '../migrations';
describe('Triggers Panel schema migration', () => { jest.mock('@grafana/runtime', () => {
let ctx: any = {}; return {
let updatePanelCtrl; getDataSourceSrv: () => ({
const datasourceSrvMock = {
getMetricSources: () => { getMetricSources: () => {
return [{ meta: {id: 'alexanderzobnin-zabbix-datasource'}, value: {}, name: 'zabbix_default' }]; return [{ meta: {id: 'alexanderzobnin-zabbix-datasource'}, value: {}, name: 'zabbix_default' }];
}, },
get: () => Promise.resolve({}) get: () => Promise.resolve({})
}),
}; };
}, {virtual: true});
describe('Triggers Panel schema migration', () => {
let ctx: any = {};
let updatePanelCtrl;
const timeoutMock = () => {}; 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', () => { it('should update old panel schema', () => {

View File

@@ -4,9 +4,16 @@ import {TriggerPanelCtrl} from '../triggers_panel_ctrl';
import {PANEL_DEFAULTS, DEFAULT_TARGET} from '../triggers_panel_ctrl'; import {PANEL_DEFAULTS, DEFAULT_TARGET} from '../triggers_panel_ctrl';
// import { create } from 'domain'; // import { create } from 'domain';
let datasourceSrvMock, zabbixDSMock;
jest.mock('@grafana/runtime', () => {
return {
getDataSourceSrv: () => datasourceSrvMock,
};
}, {virtual: true});
describe('TriggerPanelCtrl', () => { describe('TriggerPanelCtrl', () => {
let ctx: any = {}; let ctx: any = {};
let datasourceSrvMock, zabbixDSMock;
const timeoutMock = () => {}; const timeoutMock = () => {};
let createPanelCtrl; let createPanelCtrl;
@@ -31,7 +38,8 @@ describe('TriggerPanelCtrl', () => {
}, },
get: () => Promise.resolve(zabbixDSMock) get: () => Promise.resolve(zabbixDSMock)
}; };
createPanelCtrl = () => new TriggerPanelCtrl(ctx.scope, {}, timeoutMock, datasourceSrvMock, {}, {}, {}, mocks.timeSrvMock);
createPanelCtrl = () => new TriggerPanelCtrl(ctx.scope, {}, timeoutMock, {}, {}, {}, mocks.timeSrvMock);
const getTriggersResp = [ const getTriggersResp = [
[ [

View File

@@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import _ from 'lodash'; import _ from 'lodash';
import moment from 'moment'; import moment from 'moment';
import { getDataSourceSrv } from '@grafana/runtime';
import * as dateMath from 'grafana/app/core/utils/datemath'; import * as dateMath from 'grafana/app/core/utils/datemath';
import * as utils from '../datasource-zabbix/utils'; import * as utils from '../datasource-zabbix/utils';
import { PanelCtrl } from 'grafana/app/plugins/sdk'; import { PanelCtrl } from 'grafana/app/plugins/sdk';
@@ -96,9 +97,8 @@ const triggerStatusMap = {
export class TriggerPanelCtrl extends PanelCtrl { export class TriggerPanelCtrl extends PanelCtrl {
/** @ngInject */ /** @ngInject */
constructor($scope, $injector, $timeout, datasourceSrv, templateSrv, contextSrv, dashboardSrv, timeSrv) { constructor($scope, $injector, $timeout, templateSrv, contextSrv, dashboardSrv, timeSrv) {
super($scope, $injector); super($scope, $injector);
this.datasourceSrv = datasourceSrv;
this.templateSrv = templateSrv; this.templateSrv = templateSrv;
this.contextSrv = contextSrv; this.contextSrv = contextSrv;
this.dashboardSrv = dashboardSrv; this.dashboardSrv = dashboardSrv;
@@ -151,7 +151,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
const targetDatasources = _.compact(this.panel.targets.map(target => target.datasource)); const targetDatasources = _.compact(this.panel.targets.map(target => target.datasource));
let promises = targetDatasources.map(ds => { let promises = targetDatasources.map(ds => {
// Load datasource // Load datasource
return this.datasourceSrv.get(ds) return getDataSourceSrv().get(ds)
.then(datasource => { .then(datasource => {
this.datasources[ds] = datasource; this.datasources[ds] = datasource;
return datasource; return datasource;
@@ -161,7 +161,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
} }
getZabbixDataSources() { getZabbixDataSources() {
return _.filter(this.datasourceSrv.getMetricSources(), datasource => { return _.filter(getDataSourceSrv().getMetricSources(), datasource => {
return datasource.meta.id === ZABBIX_DS_ID && datasource.value; return datasource.meta.id === ZABBIX_DS_ID && datasource.value;
}); });
} }
@@ -251,7 +251,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
const ds = target.datasource; const ds = target.datasource;
let proxies; let proxies;
let showAckButton = true; let showAckButton = true;
return this.datasourceSrv.get(ds) return getDataSourceSrv().get(ds)
.then(datasource => { .then(datasource => {
const zabbix = datasource.zabbix; const zabbix = datasource.zabbix;
const showEvents = this.panel.showEvents.value; const showEvents = this.panel.showEvents.value;
@@ -524,7 +524,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
const triggerids = [problem.triggerid]; const triggerids = [problem.triggerid];
const timeFrom = Math.ceil(dateMath.parse(this.range.from) / 1000); const timeFrom = Math.ceil(dateMath.parse(this.range.from) / 1000);
const timeTo = Math.ceil(dateMath.parse(this.range.to) / 1000); const timeTo = Math.ceil(dateMath.parse(this.range.to) / 1000);
return this.datasourceSrv.get(problem.datasource) return getDataSourceSrv().get(problem.datasource)
.then(datasource => { .then(datasource => {
return datasource.zabbix.getEvents(triggerids, timeFrom, timeTo, [0, 1], PROBLEM_EVENTS_LIMIT); return datasource.zabbix.getEvents(triggerids, timeFrom, timeTo, [0, 1], PROBLEM_EVENTS_LIMIT);
}); });
@@ -535,7 +535,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
return Promise.resolve([]); return Promise.resolve([]);
} }
const eventids = [problem.lastEvent.eventid]; const eventids = [problem.lastEvent.eventid];
return this.datasourceSrv.get(problem.datasource) return getDataSourceSrv().get(problem.datasource)
.then(datasource => { .then(datasource => {
return datasource.zabbix.getEventAlerts(eventids); return datasource.zabbix.getEventAlerts(eventids);
}); });
@@ -622,7 +622,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
let eventid = trigger.lastEvent ? trigger.lastEvent.eventid : null; let eventid = trigger.lastEvent ? trigger.lastEvent.eventid : null;
let grafana_user = this.contextSrv.user.name; let grafana_user = this.contextSrv.user.name;
let ack_message = grafana_user + ' (Grafana): ' + message; let ack_message = grafana_user + ' (Grafana): ' + message;
return this.datasourceSrv.get(trigger.datasource) return getDataSourceSrv().get(trigger.datasource)
.then(datasource => { .then(datasource => {
const userIsEditor = this.contextSrv.isEditor || this.contextSrv.isGrafanaAdmin; const userIsEditor = this.contextSrv.isEditor || this.contextSrv.isGrafanaAdmin;
if (datasource.disableReadOnlyUsersAck && !userIsEditor) { if (datasource.disableReadOnlyUsersAck && !userIsEditor) {