The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/features/plugins/tests/datasource_srv.test.ts

327 lines
9.7 KiB

import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import {
DataSourceApi,
DataSourceInstanceSettings,
DataSourcePlugin,
DataSourcePluginMeta,
ScopedVar,
} from '@grafana/data';
// Datasource variable $datasource with current value 'BBB'
const templateSrv: any = {
getVariables: () => [
{
type: 'datasource',
name: 'datasource',
current: {
value: 'BBB',
},
},
{
type: 'datasource',
name: 'datasourceDefault',
current: {
value: 'default',
},
},
],
replace: (v: string, scopedVars: ScopedVar) => {
if (scopedVars && scopedVars.datasource) {
return v.replace('${datasource}', scopedVars.datasource.value);
}
let result = v.replace('${datasource}', 'BBB');
result = result.replace('${datasourceDefault}', 'default');
return result;
},
};
class TestDataSource {
constructor(public instanceSettings: DataSourceInstanceSettings) {}
}
jest.mock('../plugin_loader', () => ({
importDataSourcePlugin: (meta: DataSourcePluginMeta) => {
return Promise.resolve(new DataSourcePlugin(TestDataSource as any));
},
}));
const getBackendSrvGetMock = jest.fn();
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getBackendSrv: () => ({
get: getBackendSrvGetMock,
}),
}));
describe('datasource_srv', () => {
beforeEach(() => {
jest.resetModules();
});
const dataSourceSrv = new DatasourceSrv(templateSrv);
const dataSourceInit = {
mmm: {
type: 'test-db',
name: 'mmm',
uid: 'uid-code-mmm',
meta: { metrics: true, annotations: true } as any,
},
'-- Grafana --': {
type: 'grafana',
name: '-- Grafana --',
meta: { builtIn: true, metrics: true, id: 'grafana' },
},
'-- Dashboard --': {
type: 'dashboard',
name: '-- Dashboard --',
meta: { builtIn: true, metrics: true, id: 'dashboard' },
},
'-- Mixed --': {
type: 'test-db',
name: '-- Mixed --',
meta: { builtIn: true, metrics: true, id: 'mixed' },
},
ZZZ: {
type: 'test-db',
name: 'ZZZ',
uid: 'uid-code-ZZZ',
meta: { metrics: true },
},
aaa: {
type: 'test-db',
name: 'aaa',
uid: 'uid-code-aaa',
meta: { metrics: true },
},
BBB: {
type: 'test-db',
name: 'BBB',
uid: 'uid-code-BBB',
meta: { metrics: true },
isDefault: true,
},
Jaeger: {
type: 'jaeger-db',
name: 'Jaeger',
uid: 'uid-code-Jaeger',
meta: { tracing: true, id: 'jaeger' },
},
CannotBeQueried: {
type: 'no-query',
name: 'no-query',
uid: 'no-query',
meta: { id: 'no-query' },
},
};
describe('Given a list of data sources', () => {
beforeEach(() => {
dataSourceSrv.init(dataSourceInit as any, 'BBB');
});
describe('when getting data source class instance', () => {
it('should load plugin and create instance and set meta', async () => {
const ds = (await dataSourceSrv.get('mmm')) as any;
expect(ds.meta).toBe(dataSourceInit.mmm.meta);
expect(ds.instanceSettings).toBe(dataSourceInit.mmm);
// validate that it caches instance
const ds2 = await dataSourceSrv.get('mmm');
expect(ds).toBe(ds2);
});
it('should be able to load data source using uid as well', async () => {
const dsByUid = await dataSourceSrv.get('uid-code-mmm');
const dsByName = await dataSourceSrv.get('mmm');
expect(dsByUid.meta).toBe(dsByName.meta);
expect(dsByUid).toBe(dsByName);
});
it('should patch legacy datasources', async () => {
expect(TestDataSource instanceof DataSourceApi).toBe(false);
const instance = await dataSourceSrv.get('mmm');
expect(instance.name).toBe('mmm');
expect(instance.type).toBe('test-db');
expect(instance.uid).toBe('uid-code-mmm');
expect(instance.getRef()).toEqual({ type: 'test-db', uid: 'uid-code-mmm' });
});
it('Can get by variable', async () => {
const ds = (await dataSourceSrv.get('${datasource}')) as any;
expect(ds.meta).toBe(dataSourceInit.BBB.meta);
const ds2 = await dataSourceSrv.get('${datasource}', { datasource: { text: 'Prom', value: 'uid-code-aaa' } });
expect(ds2.uid).toBe(dataSourceInit.aaa.uid);
});
});
describe('when getting instance settings', () => {
it('should work by name or uid', () => {
const ds = dataSourceSrv.getInstanceSettings('mmm');
expect(dataSourceSrv.getInstanceSettings('uid-code-mmm')).toBe(ds);
expect(dataSourceSrv.getInstanceSettings({ uid: 'uid-code-mmm' })).toBe(ds);
});
it('should work with variable', () => {
const ds = dataSourceSrv.getInstanceSettings('${datasource}');
expect(ds?.name).toBe('${datasource}');
expect(ds?.uid).toBe('${datasource}');
expect(ds?.rawRef).toMatchInlineSnapshot(`
Object {
"type": "test-db",
"uid": "uid-code-BBB",
}
`);
});
it('should work with variable via scopedVars', () => {
const ds = dataSourceSrv.getInstanceSettings('${datasource}', {
datasource: { text: 'Prom', value: 'uid-code-aaa' },
});
expect(ds?.rawRef?.uid).toBe('uid-code-aaa');
});
it('should not set isDefault when being fetched via variable', () => {
const ds = dataSourceSrv.getInstanceSettings('${datasource}');
expect(ds?.isDefault).toBe(false);
});
it('should work with variable', () => {
const ds = dataSourceSrv.getInstanceSettings('${datasourceDefault}');
expect(ds?.name).toBe('${datasourceDefault}');
expect(ds?.uid).toBe('${datasourceDefault}');
expect(ds?.rawRef).toMatchInlineSnapshot(`
Object {
"type": "test-db",
"uid": "uid-code-BBB",
}
`);
});
});
describe('when getting external metric sources', () => {
it('should return list of explore sources', () => {
const externalSources = dataSourceSrv.getExternal();
expect(externalSources.length).toBe(6);
});
});
it('Should by default filter out data sources that cannot be queried', () => {
const list = dataSourceSrv.getList({});
expect(list.find((x) => x.name === 'no-query')).toBeUndefined();
const all = dataSourceSrv.getList({ all: true });
expect(all.find((x) => x.name === 'no-query')).toBeDefined();
});
it('Can get list of data sources with variables: true', () => {
const list = dataSourceSrv.getList({ metrics: true, variables: true });
expect(list[0].name).toBe('${datasourceDefault}');
expect(list[1].name).toBe('${datasource}');
});
it('Can get list of data sources with tracing: true', () => {
const list = dataSourceSrv.getList({ tracing: true });
expect(list[0].name).toBe('Jaeger');
});
it('Can get list of data sources with annotation: true', () => {
const list = dataSourceSrv.getList({ annotations: true });
expect(list[0].name).toBe('mmm');
});
it('Can get get list and filter by pluginId', () => {
const list = dataSourceSrv.getList({ pluginId: 'jaeger' });
expect(list[0].name).toBe('Jaeger');
expect(list.length).toBe(1);
});
it('Can get list of data sources with metrics: true, builtIn: true, mixed: true', () => {
expect(dataSourceSrv.getList({ metrics: true, dashboard: true, mixed: true })).toMatchInlineSnapshot(`
Array [
Object {
"meta": Object {
"metrics": true,
},
"name": "aaa",
"type": "test-db",
"uid": "uid-code-aaa",
},
Object {
"isDefault": true,
"meta": Object {
"metrics": true,
},
"name": "BBB",
"type": "test-db",
"uid": "uid-code-BBB",
},
Object {
"meta": Object {
"annotations": true,
"metrics": true,
},
"name": "mmm",
"type": "test-db",
"uid": "uid-code-mmm",
},
Object {
"meta": Object {
"metrics": true,
},
"name": "ZZZ",
"type": "test-db",
"uid": "uid-code-ZZZ",
},
Object {
"meta": Object {
"builtIn": true,
"id": "mixed",
"metrics": true,
},
"name": "-- Mixed --",
"type": "test-db",
"uid": "-- Mixed --",
},
Object {
"meta": Object {
"builtIn": true,
"id": "dashboard",
"metrics": true,
},
"name": "-- Dashboard --",
"type": "dashboard",
"uid": "-- Dashboard --",
},
Object {
"meta": Object {
"builtIn": true,
"id": "grafana",
"metrics": true,
},
"name": "-- Grafana --",
"type": "grafana",
"uid": "-- Grafana --",
},
]
`);
});
it('Should reload the datasource', async () => {
// arrange
getBackendSrvGetMock.mockReturnValueOnce({
datasources: {
...dataSourceInit,
},
defaultDatasource: 'aaa',
});
const initMock = jest.spyOn(dataSourceSrv, 'init').mockImplementation(() => {});
// act
await dataSourceSrv.reload();
// assert
expect(getBackendSrvGetMock).toHaveBeenCalledWith('/api/frontend/settings');
expect(initMock).toHaveBeenCalledWith(dataSourceInit, 'aaa');
});
});
});