From e2475a2189fdb45cc9413825a81f6dcb280a8f34 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Tue, 8 Apr 2025 22:51:21 +0300 Subject: [PATCH] DataSourceSrv: Get datasource of type (#101495) --- .betterer.results | 10 +++--- .../{tests => }/datasource_srv.test.ts | 31 ++++++++++++++----- public/app/features/plugins/datasource_srv.ts | 17 ++++++++++ 3 files changed, 45 insertions(+), 13 deletions(-) rename public/app/features/plugins/{tests => }/datasource_srv.test.ts (95%) diff --git a/.betterer.results b/.betterer.results index 730dabb6942..0f6c8fba7a6 100644 --- a/.betterer.results +++ b/.betterer.results @@ -2824,6 +2824,11 @@ exports[`better eslint`] = { [0, 0, 0, "No untranslated strings. Wrap text with ", "1"], [0, 0, 0, "No untranslated strings. Wrap text with ", "2"] ], + "public/app/features/plugins/datasource_srv.test.ts:5381": [ + [0, 0, 0, "Unexpected any. Specify a different type.", "0"], + [0, 0, 0, "Unexpected any. Specify a different type.", "1"], + [0, 0, 0, "Unexpected any. Specify a different type.", "2"] + ], "public/app/features/plugins/datasource_srv.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"], @@ -2847,11 +2852,6 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Do not use any type assertions.", "2"] ], - "public/app/features/plugins/tests/datasource_srv.test.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"] - ], "public/app/features/plugins/utils.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"], diff --git a/public/app/features/plugins/tests/datasource_srv.test.ts b/public/app/features/plugins/datasource_srv.test.ts similarity index 95% rename from public/app/features/plugins/tests/datasource_srv.test.ts rename to public/app/features/plugins/datasource_srv.test.ts index c23f4d9cd6b..4d2592ea4b6 100644 --- a/public/app/features/plugins/tests/datasource_srv.test.ts +++ b/public/app/features/plugins/datasource_srv.test.ts @@ -61,7 +61,7 @@ class TestRuntimeDataSource extends RuntimeDataSource { } } -jest.mock('../plugin_loader', () => ({ +jest.mock('./plugin_loader', () => ({ importDataSourcePlugin: (meta: DataSourcePluginMeta) => { return Promise.resolve(new DataSourcePlugin(TestDataSource as any)); }, @@ -90,17 +90,17 @@ describe('datasource_srv', () => { meta: { metrics: true, annotations: true }, }, '-- Grafana --': { - type: 'grafana', + type: 'datasource', name: '-- Grafana --', meta: { builtIn: true, metrics: true, id: 'grafana' }, }, '-- Dashboard --': { - type: 'dashboard', + type: 'datasource', name: '-- Dashboard --', meta: { builtIn: true, metrics: true, id: 'dashboard' }, }, '-- Mixed --': { - type: 'test-db', + type: 'datasource', name: '-- Mixed --', meta: { builtIn: true, metrics: true, id: 'mixed' }, }, @@ -144,6 +144,7 @@ describe('datasource_srv', () => { TestData: { type: 'grafana-testdata-datasource', name: 'TestData', + uid: 'testdata', meta: { metrics: true, id: 'grafana-testdata-datasource', aliasIDs: ['testdata'] }, }, }; @@ -312,6 +313,20 @@ describe('datasource_srv', () => { }); }); + describe('when getting datasource by type', () => { + it('should return the first value of each type', async () => { + const jaeger = await dataSourceSrv.get({ type: `jaeger-db` }); + const testdata = await dataSourceSrv.get({ type: `grafana-testdata-datasource` }); + expect(jaeger.uid).toBe('uid-code-Jaeger'); + expect(testdata.uid).toBe('testdata'); + }); + + it('should prefer the default value', async () => { + const api = await dataSourceSrv.get({ type: `test-db` }); + expect(api.uid).toBe('uid-code-BBB'); + }); + }); + 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(); @@ -407,7 +422,7 @@ describe('datasource_srv', () => { }, "name": "TestData", "type": "grafana-testdata-datasource", - "uid": "TestData", + "uid": "testdata", }, { "meta": { @@ -424,7 +439,7 @@ describe('datasource_srv', () => { "metrics": true, }, "name": "-- Mixed --", - "type": "test-db", + "type": "datasource", "uid": "-- Mixed --", }, { @@ -434,7 +449,7 @@ describe('datasource_srv', () => { "metrics": true, }, "name": "-- Dashboard --", - "type": "dashboard", + "type": "datasource", "uid": "-- Dashboard --", }, { @@ -444,7 +459,7 @@ describe('datasource_srv', () => { "metrics": true, }, "name": "-- Grafana --", - "type": "grafana", + "type": "datasource", "uid": "-- Grafana --", }, ] diff --git a/public/app/features/plugins/datasource_srv.ts b/public/app/features/plugins/datasource_srv.ts index e145a2e8db0..15b0fe15bd0 100644 --- a/public/app/features/plugins/datasource_srv.ts +++ b/public/app/features/plugins/datasource_srv.ts @@ -5,6 +5,7 @@ import { DataSourceRef, DataSourceSelectItem, ScopedVars, + isObject, matchPluginId, } from '@grafana/data'; import { @@ -142,6 +143,15 @@ export class DatasourceSrv implements DataSourceService { get(ref?: string | DataSourceRef | null, scopedVars?: ScopedVars): Promise { let nameOrUid = getNameOrUid(ref); if (!nameOrUid) { + // type exists, but not the other properties + if (isDatasourceRef(ref)) { + const settings = this.getList({ type: ref.type }); + if (!settings?.length) { + return Promise.reject('no datasource of type'); + } + const ds = settings.find((v) => v.isDefault) ?? settings[0]; + return this.get(ds.uid); + } return this.get(this.defaultName); } @@ -385,6 +395,13 @@ export function variableInterpolation(value: T | T[]) { return value; } +const isDatasourceRef = (ref: string | DataSourceRef | null | undefined): ref is DataSourceRef => { + if (ref && isObject(ref) && 'type' in ref) { + return true; + } + return false; +}; + export const getDatasourceSrv = (): DatasourceSrv => { return getDataSourceService() as DatasourceSrv; };