From da03175d0b8a8aa41c5f2e397a754a8d04d29344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Jamr=C3=B3z?= Date: Fri, 16 Apr 2021 08:32:33 +0200 Subject: [PATCH] Explore: Load default data source in Explore when the provided source does not exist (#32992) * Fallback to default data source in Explore and use uid for history uid is used to allow changing the name of the datasource and preserve history * Remove redundant console logs --- .../app/features/explore/state/explorePane.ts | 4 +- .../app/features/explore/state/utils.test.ts | 49 +++++++++++++++++++ public/app/features/explore/state/utils.ts | 12 ++++- 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 public/app/features/explore/state/utils.test.ts diff --git a/public/app/features/explore/state/explorePane.ts b/public/app/features/explore/state/explorePane.ts index b82abd4b8df..0db25a83fd2 100644 --- a/public/app/features/explore/state/explorePane.ts +++ b/public/app/features/explore/state/explorePane.ts @@ -127,7 +127,7 @@ export const changeDedupStrategy = ( */ export function initializeExplore( exploreId: ExploreId, - datasourceName: string, + datasourceNameOrUid: string, queries: DataQuery[], range: TimeRange, containerWidth: number, @@ -141,7 +141,7 @@ export function initializeExplore( if (exploreDatasources.length >= 1) { const orgId = getState().user.orgId; - const loadResult = await loadAndInitDatasource(orgId, datasourceName); + const loadResult = await loadAndInitDatasource(orgId, datasourceNameOrUid); instance = loadResult.instance; history = loadResult.history; } diff --git a/public/app/features/explore/state/utils.test.ts b/public/app/features/explore/state/utils.test.ts new file mode 100644 index 00000000000..401ec79924d --- /dev/null +++ b/public/app/features/explore/state/utils.test.ts @@ -0,0 +1,49 @@ +import { lastUsedDatasourceKeyForOrgId } from '../../../core/utils/explore'; + +const dataSourceMock = { + get: jest.fn(), +}; +jest.mock('app/features/plugins/datasource_srv', () => ({ + getDatasourceSrv: jest.fn(() => dataSourceMock), +})); + +const storeMock = { + getObject: jest.fn().mockReturnValue([]), + set: jest.fn(), +}; +jest.mock('app/core/store', () => storeMock); + +import { loadAndInitDatasource } from './utils'; + +const DEFAULT_DATASOURCE = { uid: 'abc123', name: 'Default' }; +const TEST_DATASOURCE = { uid: 'def789', name: 'Test' }; + +describe('loadAndInitDatasource', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('falls back to default datasource if the provided one was not found', async () => { + dataSourceMock.get.mockRejectedValueOnce(new Error('Datasource not found')); + dataSourceMock.get.mockResolvedValue(DEFAULT_DATASOURCE); + + const { instance } = await loadAndInitDatasource(1, 'Unknown'); + + expect(dataSourceMock.get).toBeCalledTimes(2); + expect(dataSourceMock.get).toBeCalledWith('Unknown'); + expect(dataSourceMock.get).toBeCalledWith(); + expect(instance).toMatchObject(DEFAULT_DATASOURCE); + expect(storeMock.set).toBeCalledWith(lastUsedDatasourceKeyForOrgId(1), DEFAULT_DATASOURCE.uid); + }); + + it('saves last loaded data source uid', async () => { + dataSourceMock.get.mockResolvedValue(TEST_DATASOURCE); + + const { instance } = await loadAndInitDatasource(1, 'Test'); + + expect(dataSourceMock.get).toBeCalledTimes(1); + expect(dataSourceMock.get).toBeCalledWith('Test'); + expect(instance).toMatchObject(TEST_DATASOURCE); + expect(storeMock.set).toBeCalledWith(lastUsedDatasourceKeyForOrgId(1), TEST_DATASOURCE.uid); + }); +}); diff --git a/public/app/features/explore/state/utils.ts b/public/app/features/explore/state/utils.ts index c25d49199a3..c7373f63b19 100644 --- a/public/app/features/explore/state/utils.ts +++ b/public/app/features/explore/state/utils.ts @@ -63,7 +63,15 @@ export async function loadAndInitDatasource( orgId: number, datasourceName?: string ): Promise<{ history: HistoryItem[]; instance: DataSourceApi }> { - const instance = await getDatasourceSrv().get(datasourceName); + let instance; + try { + instance = await getDatasourceSrv().get(datasourceName); + } catch (error) { + // Falling back to the default data source in case the provided data source was not found. + // It may happen if last used data source or the data source provided in the URL has been + // removed or it is not provisioned anymore. + instance = await getDatasourceSrv().get(); + } if (instance.init) { try { instance.init(); @@ -77,7 +85,7 @@ export async function loadAndInitDatasource( const history = store.getObject(historyKey, []); // Save last-used datasource - store.set(lastUsedDatasourceKeyForOrgId(orgId), instance.name); + store.set(lastUsedDatasourceKeyForOrgId(orgId), instance.uid); return { history, instance }; }