From fc7edab8fd2cb2042c2a665dfacfcf9b1067208f Mon Sep 17 00:00:00 2001 From: Timothy Palpant Date: Fri, 13 Nov 2020 07:11:24 -0500 Subject: [PATCH] Plugins: Implement testDatasource for Jaeger (#28916) * Implement testDatasource for Jaeger * Unit tests * Run prettier --- .../datasource/jaeger/datasource.test.ts | 97 +++++++++++++++++++ .../plugins/datasource/jaeger/datasource.ts | 38 +++++++- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/datasource/jaeger/datasource.test.ts b/public/app/plugins/datasource/jaeger/datasource.test.ts index 5ecdce4d36b..3941ec12174 100644 --- a/public/app/plugins/datasource/jaeger/datasource.test.ts +++ b/public/app/plugins/datasource/jaeger/datasource.test.ts @@ -53,6 +53,103 @@ describe('JaegerDatasource', () => { }); }); +describe('when performing testDataSource', () => { + describe('and call succeeds', () => { + it('should return successfully', async () => { + const backendSrvMock = makeTestDatasourceMock( + Promise.resolve({ + statusText: 'OK', + status: 200, + data: { + data: ['service1'], + }, + }) + ); + + await withMockedBackendSrv(backendSrvMock, async () => { + const ds = new JaegerDatasource(defaultSettings); + const response = await ds.testDatasource(); + expect(response.status).toEqual('success'); + expect(response.message).toBe('Data source connected and services found.'); + }); + }); + }); + + describe('and call succeeds, but returns no services', () => { + it('should display an error', async () => { + const backendSrvMock = makeTestDatasourceMock( + Promise.resolve({ + statusText: 'OK', + status: 200, + }) + ); + + await withMockedBackendSrv(backendSrvMock, async () => { + const ds = new JaegerDatasource(defaultSettings); + const response = await ds.testDatasource(); + expect(response.status).toEqual('error'); + expect(response.message).toBe( + 'Data source connected, but no services received. Verify that Jaeger is configured properly.' + ); + }); + }); + }); + + describe('and call returns error with message', () => { + it('should return the formatted error', async () => { + const backendSrvMock = { + datasourceRequest(options: BackendSrvRequest): Promise { + return Promise.reject({ + statusText: 'Not found', + status: 404, + data: { + message: '404 page not found', + }, + }); + }, + } as BackendSrv; + + await withMockedBackendSrv(backendSrvMock, async () => { + const ds = new JaegerDatasource(defaultSettings); + const response = await ds.testDatasource(); + expect(response.status).toEqual('error'); + expect(response.message).toBe('Jaeger: Not found. 404. 404 page not found'); + }); + }); + }); + + describe('and call returns error without message', () => { + it('should return JSON error', async () => { + const backendSrvMock = { + datasourceRequest(options: BackendSrvRequest): Promise { + return Promise.reject({ + statusText: 'Bad gateway', + status: 502, + data: { + errors: ['Could not connect to Jaeger backend'], + }, + }); + }, + } as BackendSrv; + + await withMockedBackendSrv(backendSrvMock, async () => { + const ds = new JaegerDatasource(defaultSettings); + const response = await ds.testDatasource(); + expect(response.status).toEqual('error'); + expect(response.message).toBe('Jaeger: Bad gateway. 502. {"errors":["Could not connect to Jaeger backend"]}'); + }); + }); + }); +}); + +function makeTestDatasourceMock(result: Promise) { + return { + datasourceRequest(options: BackendSrvRequest): Promise { + return result; + }, + } as BackendSrv; +} + function makeBackendSrvMock(traceId: string) { return { datasourceRequest(options: BackendSrvRequest): Promise { diff --git a/public/app/plugins/datasource/jaeger/datasource.ts b/public/app/plugins/datasource/jaeger/datasource.ts index 0dc337a727e..eefd34e6c01 100644 --- a/public/app/plugins/datasource/jaeger/datasource.ts +++ b/public/app/plugins/datasource/jaeger/datasource.ts @@ -11,7 +11,7 @@ import { } from '@grafana/data'; import { getBackendSrv, BackendSrvRequest } from '@grafana/runtime'; import { Observable, from, of } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { catchError, map } from 'rxjs/operators'; import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { serializeParams } from 'app/core/utils/fetch'; @@ -77,7 +77,41 @@ export class JaegerDatasource extends DataSourceApi { } async testDatasource(): Promise { - return true; + return this._request('/api/services') + .pipe( + map(res => { + const values: any[] = res?.data?.data || []; + const testResult = + values.length > 0 + ? { status: 'success', message: 'Data source connected and services found.' } + : { + status: 'error', + message: + 'Data source connected, but no services received. Verify that Jaeger is configured properly.', + }; + return testResult; + }), + catchError((err: any) => { + let message = 'Jaeger: '; + if (err.statusText) { + message += err.statusText; + } else { + message += 'Cannot connect to Jaeger'; + } + + if (err.status) { + message += `. ${err.status}`; + } + + if (err.data && err.data.message) { + message += `. ${err.data.message}`; + } else if (err.data) { + message += `. ${JSON.stringify(err.data)}`; + } + return of({ status: 'error', message: message }); + }) + ) + .toPromise(); } getTimeRange(): { start: number; end: number } {