mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DataSourceSrv: Look up data source by uid and name transparently (#29449)
* Datasources: Look up data source by uid or name transparently * comment tweak * Removed config * fixed type issues * Initialize datasource srv * Added deprecation notice * Renamed getSettingsFor to getInstanceSettings * fixed ts issue
This commit is contained in:
parent
b7aa6fed1d
commit
38caa80acd
@ -17,6 +17,7 @@ export interface DataSourceSrv {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns metadata based on UID.
|
* Returns metadata based on UID.
|
||||||
|
* @deprecated use getInstanceSettings
|
||||||
*/
|
*/
|
||||||
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined;
|
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined;
|
||||||
|
|
||||||
@ -29,6 +30,11 @@ export interface DataSourceSrv {
|
|||||||
* Get all data sources except for internal ones that usually should not be listed like mixed data source.
|
* Get all data sources except for internal ones that usually should not be listed like mixed data source.
|
||||||
*/
|
*/
|
||||||
getExternal(): DataSourceInstanceSettings[];
|
getExternal(): DataSourceInstanceSettings[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get settings and plugin metadata by name or uid
|
||||||
|
*/
|
||||||
|
getInstanceSettings(nameOrUid: string | null | undefined): DataSourceInstanceSettings | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let singletonInstance: DataSourceSrv;
|
let singletonInstance: DataSourceSrv;
|
||||||
|
@ -19,19 +19,10 @@ const backendSrv = ({
|
|||||||
|
|
||||||
jest.mock('../services', () => ({
|
jest.mock('../services', () => ({
|
||||||
getBackendSrv: () => backendSrv,
|
getBackendSrv: () => backendSrv,
|
||||||
}));
|
getDataSourceSrv: () => {
|
||||||
jest.mock('..', () => ({
|
return {
|
||||||
config: {
|
getInstanceSettings: () => ({ id: 8674 }),
|
||||||
bootData: {
|
};
|
||||||
user: {
|
|
||||||
orgId: 77,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
datasources: {
|
|
||||||
sample: {
|
|
||||||
id: 8674,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -46,6 +37,7 @@ describe('DataSourceWithBackend', () => {
|
|||||||
mockDatasourceRequest.mockReset();
|
mockDatasourceRequest.mockReset();
|
||||||
mockDatasourceRequest.mockReturnValue(Promise.resolve({}));
|
mockDatasourceRequest.mockReturnValue(Promise.resolve({}));
|
||||||
const ds = new MyDataSource(settings);
|
const ds = new MyDataSource(settings);
|
||||||
|
|
||||||
ds.query({
|
ds.query({
|
||||||
maxDataPoints: 10,
|
maxDataPoints: 10,
|
||||||
intervalMs: 5000,
|
intervalMs: 5000,
|
||||||
@ -64,7 +56,6 @@ describe('DataSourceWithBackend', () => {
|
|||||||
"datasourceId": 1234,
|
"datasourceId": 1234,
|
||||||
"intervalMs": 5000,
|
"intervalMs": 5000,
|
||||||
"maxDataPoints": 10,
|
"maxDataPoints": 10,
|
||||||
"orgId": 77,
|
|
||||||
"refId": "A",
|
"refId": "A",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
@ -72,7 +63,6 @@ describe('DataSourceWithBackend', () => {
|
|||||||
"datasourceId": 8674,
|
"datasourceId": 8674,
|
||||||
"intervalMs": 5000,
|
"intervalMs": 5000,
|
||||||
"maxDataPoints": 10,
|
"maxDataPoints": 10,
|
||||||
"orgId": 77,
|
|
||||||
"refId": "B",
|
"refId": "B",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -9,8 +9,7 @@ import {
|
|||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { map, catchError } from 'rxjs/operators';
|
import { map, catchError } from 'rxjs/operators';
|
||||||
import { config } from '..';
|
import { getBackendSrv, getDataSourceSrv } from '../services';
|
||||||
import { getBackendSrv } from '../services';
|
|
||||||
import { toDataQueryResponse } from './queryResponse';
|
import { toDataQueryResponse } from './queryResponse';
|
||||||
|
|
||||||
const ExpressionDatasourceID = '__expr__';
|
const ExpressionDatasourceID = '__expr__';
|
||||||
@ -57,34 +56,37 @@ export class DataSourceWithBackend<
|
|||||||
*/
|
*/
|
||||||
query(request: DataQueryRequest<TQuery>): Observable<DataQueryResponse> {
|
query(request: DataQueryRequest<TQuery>): Observable<DataQueryResponse> {
|
||||||
const { intervalMs, maxDataPoints, range, requestId } = request;
|
const { intervalMs, maxDataPoints, range, requestId } = request;
|
||||||
const orgId = config.bootData.user.orgId;
|
|
||||||
let targets = request.targets;
|
let targets = request.targets;
|
||||||
|
|
||||||
if (this.filterQuery) {
|
if (this.filterQuery) {
|
||||||
targets = targets.filter(q => this.filterQuery!(q));
|
targets = targets.filter(q => this.filterQuery!(q));
|
||||||
}
|
}
|
||||||
|
|
||||||
const queries = targets.map(q => {
|
const queries = targets.map(q => {
|
||||||
let datasourceId = this.id;
|
let datasourceId = this.id;
|
||||||
|
|
||||||
if (q.datasource === ExpressionDatasourceID) {
|
if (q.datasource === ExpressionDatasourceID) {
|
||||||
return {
|
return {
|
||||||
...q,
|
...q,
|
||||||
datasourceId,
|
datasourceId,
|
||||||
orgId,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q.datasource) {
|
if (q.datasource) {
|
||||||
const dsName = q.datasource === 'default' ? config.defaultDatasource : q.datasource;
|
const ds = getDataSourceSrv().getInstanceSettings(q.datasource);
|
||||||
const ds = config.datasources[dsName];
|
|
||||||
if (!ds) {
|
if (!ds) {
|
||||||
throw new Error('Unknown Datasource: ' + q.datasource);
|
throw new Error('Unknown Datasource: ' + q.datasource);
|
||||||
}
|
}
|
||||||
|
|
||||||
datasourceId = ds.id;
|
datasourceId = ds.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...this.applyTemplateVariables(q, request.scopedVars),
|
...this.applyTemplateVariables(q, request.scopedVars),
|
||||||
datasourceId,
|
datasourceId,
|
||||||
intervalMs,
|
intervalMs,
|
||||||
maxDataPoints,
|
maxDataPoints,
|
||||||
orgId,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -93,9 +95,8 @@ export class DataSourceWithBackend<
|
|||||||
return of({ data: [] });
|
return of({ data: [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
const body: any = {
|
const body: any = { queries };
|
||||||
queries,
|
|
||||||
};
|
|
||||||
if (range) {
|
if (range) {
|
||||||
body.range = range;
|
body.range = range;
|
||||||
body.from = range.from.valueOf().toString();
|
body.from = range.from.valueOf().toString();
|
||||||
|
@ -26,6 +26,7 @@ describe('getAlertingValidationMessage', () => {
|
|||||||
getExternal(): DataSourceInstanceSettings[] {
|
getExternal(): DataSourceInstanceSettings[] {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
|
getInstanceSettings: (() => {}) as any,
|
||||||
getAll(): DataSourceInstanceSettings[] {
|
getAll(): DataSourceInstanceSettings[] {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
@ -66,6 +67,7 @@ describe('getAlertingValidationMessage', () => {
|
|||||||
return Promise.resolve(alertingDatasource);
|
return Promise.resolve(alertingDatasource);
|
||||||
},
|
},
|
||||||
getDataSourceSettingsByUid(): any {},
|
getDataSourceSettingsByUid(): any {},
|
||||||
|
getInstanceSettings: (() => {}) as any,
|
||||||
getExternal(): DataSourceInstanceSettings[] {
|
getExternal(): DataSourceInstanceSettings[] {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
@ -96,6 +98,7 @@ describe('getAlertingValidationMessage', () => {
|
|||||||
const datasourceSrv: DataSourceSrv = {
|
const datasourceSrv: DataSourceSrv = {
|
||||||
get: getMock,
|
get: getMock,
|
||||||
getDataSourceSettingsByUid(): any {},
|
getDataSourceSettingsByUid(): any {},
|
||||||
|
getInstanceSettings: (() => {}) as any,
|
||||||
getExternal(): DataSourceInstanceSettings[] {
|
getExternal(): DataSourceInstanceSettings[] {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
@ -128,6 +131,7 @@ describe('getAlertingValidationMessage', () => {
|
|||||||
const datasourceSrv: DataSourceSrv = {
|
const datasourceSrv: DataSourceSrv = {
|
||||||
get: getMock,
|
get: getMock,
|
||||||
getDataSourceSettingsByUid(): any {},
|
getDataSourceSettingsByUid(): any {},
|
||||||
|
getInstanceSettings: (() => {}) as any,
|
||||||
getExternal(): DataSourceInstanceSettings[] {
|
getExternal(): DataSourceInstanceSettings[] {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
@ -160,6 +164,7 @@ describe('getAlertingValidationMessage', () => {
|
|||||||
const datasourceSrv: DataSourceSrv = {
|
const datasourceSrv: DataSourceSrv = {
|
||||||
get: getMock,
|
get: getMock,
|
||||||
getDataSourceSettingsByUid(): any {},
|
getDataSourceSettingsByUid(): any {},
|
||||||
|
getInstanceSettings: (() => {}) as any,
|
||||||
getExternal(): DataSourceInstanceSettings[] {
|
getExternal(): DataSourceInstanceSettings[] {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
|
@ -214,7 +214,7 @@ function updateFrontendSettings() {
|
|||||||
.then((settings: any) => {
|
.then((settings: any) => {
|
||||||
config.datasources = settings.datasources;
|
config.datasources = settings.datasources;
|
||||||
config.defaultDatasource = settings.defaultDatasource;
|
config.defaultDatasource = settings.defaultDatasource;
|
||||||
getDatasourceSrv().init();
|
getDatasourceSrv().init(config.datasources, settings.defaultDatasource);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,9 @@ export class GrafanaLiveDataSourceScope extends GrafanaLiveScope {
|
|||||||
if (this.names) {
|
if (this.names) {
|
||||||
return Promise.resolve(this.names);
|
return Promise.resolve(this.names);
|
||||||
}
|
}
|
||||||
|
|
||||||
const names: Array<SelectableValue<string>> = [];
|
const names: Array<SelectableValue<string>> = [];
|
||||||
|
|
||||||
for (const [key, ds] of Object.entries(config.datasources)) {
|
for (const [key, ds] of Object.entries(config.datasources)) {
|
||||||
if (ds.meta.live) {
|
if (ds.meta.live) {
|
||||||
try {
|
try {
|
||||||
@ -99,6 +101,7 @@ export class GrafanaLiveDataSourceScope extends GrafanaLiveScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (this.names = names);
|
return (this.names = names);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import sortBy from 'lodash/sortBy';
|
import sortBy from 'lodash/sortBy';
|
||||||
import coreModule from 'app/core/core_module';
|
import coreModule from 'app/core/core_module';
|
||||||
// Services & Utils
|
// Services & Utils
|
||||||
import config from 'app/core/config';
|
|
||||||
import { importDataSourcePlugin } from './plugin_loader';
|
import { importDataSourcePlugin } from './plugin_loader';
|
||||||
import {
|
import {
|
||||||
DataSourceSrv as DataSourceService,
|
DataSourceSrv as DataSourceService,
|
||||||
@ -18,47 +17,74 @@ import { expressionDatasource } from 'app/features/expressions/ExpressionDatasou
|
|||||||
import { DataSourceVariableModel } from '../variables/types';
|
import { DataSourceVariableModel } from '../variables/types';
|
||||||
|
|
||||||
export class DatasourceSrv implements DataSourceService {
|
export class DatasourceSrv implements DataSourceService {
|
||||||
datasources: Record<string, DataSourceApi> = {};
|
private datasources: Record<string, DataSourceApi> = {};
|
||||||
|
private settingsMapByName: Record<string, DataSourceInstanceSettings> = {};
|
||||||
|
private settingsMapByUid: Record<string, DataSourceInstanceSettings> = {};
|
||||||
|
private defaultName = '';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
private $injector: auto.IInjectorService,
|
private $injector: auto.IInjectorService,
|
||||||
private $rootScope: GrafanaRootScope,
|
private $rootScope: GrafanaRootScope,
|
||||||
private templateSrv: TemplateSrv
|
private templateSrv: TemplateSrv
|
||||||
) {
|
) {}
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
init(settingsMapByName: Record<string, DataSourceInstanceSettings>, defaultName: string) {
|
||||||
this.datasources = {};
|
this.datasources = {};
|
||||||
|
this.settingsMapByUid = {};
|
||||||
|
this.settingsMapByName = settingsMapByName;
|
||||||
|
this.defaultName = defaultName;
|
||||||
|
|
||||||
|
for (const dsSettings of Object.values(settingsMapByName)) {
|
||||||
|
this.settingsMapByUid[dsSettings.uid] = dsSettings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined {
|
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined {
|
||||||
return Object.values(config.datasources).find(ds => ds.uid === uid);
|
return this.settingsMapByUid[uid];
|
||||||
}
|
}
|
||||||
|
|
||||||
get(name?: string | null, scopedVars?: ScopedVars): Promise<DataSourceApi> {
|
getInstanceSettings(nameOrUid: string | null | undefined): DataSourceInstanceSettings | undefined {
|
||||||
if (!name) {
|
if (nameOrUid === 'default' || nameOrUid === null || nameOrUid === undefined) {
|
||||||
return this.get(config.defaultDatasource);
|
return this.settingsMapByName[this.defaultName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.settingsMapByUid[nameOrUid] ?? this.settingsMapByName[nameOrUid];
|
||||||
|
}
|
||||||
|
|
||||||
|
get(nameOrUid?: string | null, scopedVars?: ScopedVars): Promise<DataSourceApi> {
|
||||||
|
if (!nameOrUid) {
|
||||||
|
return this.get(this.defaultName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if nameOrUid matches a uid and then get the name
|
||||||
|
const byUid = this.settingsMapByUid[nameOrUid];
|
||||||
|
if (byUid) {
|
||||||
|
nameOrUid = byUid.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This check is duplicated below, this is here mainly as performance optimization to skip interpolation
|
||||||
|
if (this.datasources[nameOrUid]) {
|
||||||
|
return Promise.resolve(this.datasources[nameOrUid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolation here is to support template variable in data source selection
|
// Interpolation here is to support template variable in data source selection
|
||||||
name = this.templateSrv.replace(name, scopedVars, (value: any[]) => {
|
nameOrUid = this.templateSrv.replace(nameOrUid, scopedVars, (value: any[]) => {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
return value[0];
|
return value[0];
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (name === 'default') {
|
if (nameOrUid === 'default') {
|
||||||
return this.get(config.defaultDatasource);
|
return this.get(this.defaultName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.datasources[name]) {
|
if (this.datasources[nameOrUid]) {
|
||||||
return Promise.resolve(this.datasources[name]);
|
return Promise.resolve(this.datasources[nameOrUid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.loadDatasource(name);
|
return this.loadDatasource(nameOrUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadDatasource(name: string): Promise<DataSourceApi<any, any>> {
|
async loadDatasource(name: string): Promise<DataSourceApi<any, any>> {
|
||||||
@ -68,7 +94,7 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
return Promise.resolve(expressionDatasource);
|
return Promise.resolve(expressionDatasource);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dsConfig = config.datasources[name];
|
const dsConfig = this.settingsMapByName[name];
|
||||||
if (!dsConfig) {
|
if (!dsConfig) {
|
||||||
return Promise.reject({ message: `Datasource named ${name} was not found` });
|
return Promise.reject({ message: `Datasource named ${name} was not found` });
|
||||||
}
|
}
|
||||||
@ -101,8 +127,7 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAll(): DataSourceInstanceSettings[] {
|
getAll(): DataSourceInstanceSettings[] {
|
||||||
const { datasources } = config;
|
return Object.values(this.settingsMapByName);
|
||||||
return Object.keys(datasources).map(name => datasources[name]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getExternal(): DataSourceInstanceSettings[] {
|
getExternal(): DataSourceInstanceSettings[] {
|
||||||
@ -115,7 +140,7 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
|
|
||||||
this.addDataSourceVariables(sources);
|
this.addDataSourceVariables(sources);
|
||||||
|
|
||||||
Object.values(config.datasources).forEach(value => {
|
Object.values(this.settingsMapByName).forEach(value => {
|
||||||
if (value.meta?.annotations) {
|
if (value.meta?.annotations) {
|
||||||
sources.push(value);
|
sources.push(value);
|
||||||
}
|
}
|
||||||
@ -127,7 +152,7 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
getMetricSources(options?: { skipVariables?: boolean }) {
|
getMetricSources(options?: { skipVariables?: boolean }) {
|
||||||
const metricSources: DataSourceSelectItem[] = [];
|
const metricSources: DataSourceSelectItem[] = [];
|
||||||
|
|
||||||
Object.entries(config.datasources).forEach(([key, value]) => {
|
Object.entries(this.settingsMapByName).forEach(([key, value]) => {
|
||||||
if (value.meta?.metrics) {
|
if (value.meta?.metrics) {
|
||||||
let metricSource: DataSourceSelectItem = { value: key, name: key, meta: value.meta, sort: key };
|
let metricSource: DataSourceSelectItem = { value: key, name: key, meta: value.meta, sort: key };
|
||||||
|
|
||||||
@ -142,7 +167,7 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
|
|
||||||
metricSources.push(metricSource);
|
metricSources.push(metricSource);
|
||||||
|
|
||||||
if (key === config.defaultDatasource) {
|
if (key === this.defaultName) {
|
||||||
metricSource = { value: null, name: 'default', meta: value.meta, sort: key };
|
metricSource = { value: null, name: 'default', meta: value.meta, sort: key };
|
||||||
metricSources.push(metricSource);
|
metricSources.push(metricSource);
|
||||||
}
|
}
|
||||||
@ -172,9 +197,9 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
.getVariables()
|
.getVariables()
|
||||||
.filter(variable => variable.type === 'datasource')
|
.filter(variable => variable.type === 'datasource')
|
||||||
.forEach((variable: DataSourceVariableModel) => {
|
.forEach((variable: DataSourceVariableModel) => {
|
||||||
const first = variable.current.value === 'default' ? config.defaultDatasource : variable.current.value;
|
const first = variable.current.value === 'default' ? this.defaultName : variable.current.value;
|
||||||
const index = (first as unknown) as string;
|
const index = (first as unknown) as string;
|
||||||
const ds = config.datasources[index];
|
const ds = this.settingsMapByName[index];
|
||||||
|
|
||||||
if (ds) {
|
if (ds) {
|
||||||
const key = `$${variable.name}`;
|
const key = `$${variable.name}`;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import config from 'app/core/config';
|
|
||||||
import 'app/features/plugins/datasource_srv';
|
import 'app/features/plugins/datasource_srv';
|
||||||
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { DataSourcePluginMeta, PluginMeta } from '@grafana/data';
|
import { DataSourceInstanceSettings, DataSourcePlugin, DataSourcePluginMeta, PluginMeta } from '@grafana/data';
|
||||||
|
|
||||||
// Datasource variable $datasource with current value 'BBB'
|
// Datasource variable $datasource with current value 'BBB'
|
||||||
const templateSrv: any = {
|
const templateSrv: any = {
|
||||||
@ -14,41 +13,72 @@ const templateSrv: any = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
replace: (v: string) => v,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TestDataSource {
|
||||||
|
constructor(public instanceSettings: DataSourceInstanceSettings) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.mock('../plugin_loader', () => ({
|
||||||
|
importDataSourcePlugin: () => {
|
||||||
|
return Promise.resolve(new DataSourcePlugin(TestDataSource as any));
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe('datasource_srv', () => {
|
describe('datasource_srv', () => {
|
||||||
const _datasourceSrv = new DatasourceSrv({} as any, {} as any, templateSrv);
|
const _datasourceSrv = new DatasourceSrv({} as any, {} as any, templateSrv);
|
||||||
|
const datasources = {
|
||||||
|
buildIn: {
|
||||||
|
id: 1,
|
||||||
|
uid: '1',
|
||||||
|
type: 'b',
|
||||||
|
name: 'buildIn',
|
||||||
|
meta: { builtIn: true } as DataSourcePluginMeta,
|
||||||
|
jsonData: {},
|
||||||
|
},
|
||||||
|
external1: {
|
||||||
|
id: 2,
|
||||||
|
uid: '2',
|
||||||
|
type: 'e',
|
||||||
|
name: 'external1',
|
||||||
|
meta: { builtIn: false } as DataSourcePluginMeta,
|
||||||
|
jsonData: {},
|
||||||
|
},
|
||||||
|
external2: {
|
||||||
|
id: 3,
|
||||||
|
uid: '3',
|
||||||
|
type: 'e2',
|
||||||
|
name: 'external2',
|
||||||
|
meta: {} as PluginMeta,
|
||||||
|
jsonData: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
describe('when loading external datasources', () => {
|
beforeEach(() => {
|
||||||
beforeEach(() => {
|
_datasourceSrv.init(datasources, 'external1');
|
||||||
config.datasources = {
|
});
|
||||||
buildInDs: {
|
|
||||||
id: 1,
|
describe('when getting data source class instance', () => {
|
||||||
uid: '1',
|
it('should load plugin and create instance and set meta', async () => {
|
||||||
type: 'b',
|
const ds = (await _datasourceSrv.get('external1')) as any;
|
||||||
name: 'buildIn',
|
expect(ds.meta).toBe(datasources.external1.meta);
|
||||||
meta: { builtIn: true } as DataSourcePluginMeta,
|
expect(ds.instanceSettings).toBe(datasources.external1);
|
||||||
jsonData: {},
|
|
||||||
},
|
// validate that it caches instance
|
||||||
nonBuildIn: {
|
const ds2 = await _datasourceSrv.get('external1');
|
||||||
id: 2,
|
expect(ds).toBe(ds2);
|
||||||
uid: '2',
|
|
||||||
type: 'e',
|
|
||||||
name: 'external1',
|
|
||||||
meta: { builtIn: false } as DataSourcePluginMeta,
|
|
||||||
jsonData: {},
|
|
||||||
},
|
|
||||||
nonExplore: {
|
|
||||||
id: 3,
|
|
||||||
uid: '3',
|
|
||||||
type: 'e2',
|
|
||||||
name: 'external2',
|
|
||||||
meta: {} as PluginMeta,
|
|
||||||
jsonData: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to load data source using uid as well', async () => {
|
||||||
|
const dsByUid = await _datasourceSrv.get('2');
|
||||||
|
const dsByName = await _datasourceSrv.get('external1');
|
||||||
|
expect(dsByUid.meta).toBe(datasources.external1.meta);
|
||||||
|
expect(dsByUid).toBe(dsByName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when getting external metric sources', () => {
|
||||||
it('should return list of explore sources', () => {
|
it('should return list of explore sources', () => {
|
||||||
const externalSources = _datasourceSrv.getExternal();
|
const externalSources = _datasourceSrv.getExternal();
|
||||||
expect(externalSources.length).toBe(2);
|
expect(externalSources.length).toBe(2);
|
||||||
@ -59,45 +89,48 @@ describe('datasource_srv', () => {
|
|||||||
|
|
||||||
describe('when loading metric sources', () => {
|
describe('when loading metric sources', () => {
|
||||||
let metricSources: any;
|
let metricSources: any;
|
||||||
const unsortedDatasources = {
|
|
||||||
mmm: {
|
|
||||||
type: 'test-db',
|
|
||||||
meta: { metrics: { m: 1 } },
|
|
||||||
},
|
|
||||||
'--Grafana--': {
|
|
||||||
type: 'grafana',
|
|
||||||
meta: { builtIn: true, metrics: { m: 1 }, id: 'grafana' },
|
|
||||||
},
|
|
||||||
'--Mixed--': {
|
|
||||||
type: 'test-db',
|
|
||||||
meta: { builtIn: true, metrics: { m: 1 }, id: 'mixed' },
|
|
||||||
},
|
|
||||||
ZZZ: {
|
|
||||||
type: 'test-db',
|
|
||||||
meta: { metrics: { m: 1 } },
|
|
||||||
},
|
|
||||||
aaa: {
|
|
||||||
type: 'test-db',
|
|
||||||
meta: { metrics: { m: 1 } },
|
|
||||||
},
|
|
||||||
BBB: {
|
|
||||||
type: 'test-db',
|
|
||||||
meta: { metrics: { m: 1 } },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
config.datasources = unsortedDatasources as any;
|
_datasourceSrv.init(
|
||||||
|
{
|
||||||
|
mmm: {
|
||||||
|
type: 'test-db',
|
||||||
|
meta: { metrics: true } as any,
|
||||||
|
},
|
||||||
|
'--Grafana--': {
|
||||||
|
type: 'grafana',
|
||||||
|
meta: { builtIn: true, metrics: true, id: 'grafana' },
|
||||||
|
},
|
||||||
|
'--Mixed--': {
|
||||||
|
type: 'test-db',
|
||||||
|
meta: { builtIn: true, metrics: true, id: 'mixed' },
|
||||||
|
},
|
||||||
|
ZZZ: {
|
||||||
|
type: 'test-db',
|
||||||
|
meta: { metrics: true },
|
||||||
|
},
|
||||||
|
aaa: {
|
||||||
|
type: 'test-db',
|
||||||
|
meta: { metrics: true },
|
||||||
|
},
|
||||||
|
BBB: {
|
||||||
|
type: 'test-db',
|
||||||
|
meta: { metrics: true },
|
||||||
|
},
|
||||||
|
} as any,
|
||||||
|
'BBB'
|
||||||
|
);
|
||||||
metricSources = _datasourceSrv.getMetricSources({});
|
metricSources = _datasourceSrv.getMetricSources({});
|
||||||
config.defaultDatasource = 'BBB';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a list of sources sorted case insensitively with builtin sources last', () => {
|
it('should return a list of sources sorted case insensitively with builtin sources last', () => {
|
||||||
expect(metricSources[1].name).toBe('aaa');
|
expect(metricSources[1].name).toBe('aaa');
|
||||||
expect(metricSources[2].name).toBe('BBB');
|
expect(metricSources[2].name).toBe('BBB');
|
||||||
expect(metricSources[3].name).toBe('mmm');
|
expect(metricSources[3].name).toBe('default');
|
||||||
expect(metricSources[4].name).toBe('ZZZ');
|
expect(metricSources[4].name).toBe('mmm');
|
||||||
expect(metricSources[5].name).toBe('--Grafana--');
|
expect(metricSources[5].name).toBe('ZZZ');
|
||||||
expect(metricSources[6].name).toBe('--Mixed--');
|
expect(metricSources[6].name).toBe('--Grafana--');
|
||||||
|
expect(metricSources[7].name).toBe('--Mixed--');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set default data source', () => {
|
it('should set default data source', () => {
|
||||||
|
@ -62,6 +62,8 @@ export class GrafanaCtrl {
|
|||||||
setDashboardSrv(dashboardSrv);
|
setDashboardSrv(dashboardSrv);
|
||||||
setLegacyAngularInjector($injector);
|
setLegacyAngularInjector($injector);
|
||||||
|
|
||||||
|
datasourceSrv.init(config.datasources, config.defaultDatasource);
|
||||||
|
|
||||||
locationUtil.initialize({
|
locationUtil.initialize({
|
||||||
getConfig: () => config,
|
getConfig: () => config,
|
||||||
getTimeRangeForUrl: getTimeSrv().timeRangeForUrl,
|
getTimeRangeForUrl: getTimeSrv().timeRangeForUrl,
|
||||||
|
Loading…
Reference in New Issue
Block a user