mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DataSourceApi: convert interface to abstract class (#16979)
* DataSourceApi as class * add diff signature * Prometheus: moved directUrl to jsonData
This commit is contained in:
parent
5573d28582
commit
1d7bb2a763
@ -117,15 +117,30 @@ export interface DataSourceConstructor<
|
||||
/**
|
||||
* The main data source abstraction interface, represents an instance of a data source
|
||||
*/
|
||||
export interface DataSourceApi<
|
||||
export abstract class DataSourceApi<
|
||||
TQuery extends DataQuery = DataQuery,
|
||||
TOptions extends DataSourceJsonData = DataSourceJsonData
|
||||
> {
|
||||
/**
|
||||
* Set in constructor
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* Set in constructor
|
||||
*/
|
||||
readonly id: number;
|
||||
|
||||
/**
|
||||
* min interval range
|
||||
*/
|
||||
interval?: string;
|
||||
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<TOptions>) {
|
||||
this.name = instanceSettings.name;
|
||||
this.id = instanceSettings.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports queries from a different datasource
|
||||
*/
|
||||
@ -139,12 +154,12 @@ export interface DataSourceApi<
|
||||
/**
|
||||
* Main metrics / data query action
|
||||
*/
|
||||
query(options: DataQueryRequest<TQuery>, observer?: DataStreamObserver): Promise<DataQueryResponse>;
|
||||
abstract query(options: DataQueryRequest<TQuery>, observer?: DataStreamObserver): Promise<DataQueryResponse>;
|
||||
|
||||
/**
|
||||
* Test & verify datasource settings & connection details
|
||||
*/
|
||||
testDatasource(): Promise<any>;
|
||||
abstract testDatasource(): Promise<any>;
|
||||
|
||||
/**
|
||||
* Get hints for query improvements
|
||||
@ -156,16 +171,6 @@ export interface DataSourceApi<
|
||||
*/
|
||||
getQueryDisplayText?(query: TQuery): string;
|
||||
|
||||
/**
|
||||
* Set after constructor is called by Grafana
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Set after constructor is called by Grafana
|
||||
*/
|
||||
id?: number;
|
||||
|
||||
/**
|
||||
* Set after constructor call, as the data source instance is the most common thing to pass around
|
||||
* we attach the components to this instance for easy access
|
||||
@ -178,7 +183,7 @@ export interface DataSourceApi<
|
||||
meta?: DataSourcePluginMeta;
|
||||
}
|
||||
|
||||
export interface ExploreDataSourceApi<
|
||||
export abstract class ExploreDataSourceApi<
|
||||
TQuery extends DataQuery = DataQuery,
|
||||
TOptions extends DataSourceJsonData = DataSourceJsonData
|
||||
> extends DataSourceApi<TQuery, TOptions> {
|
||||
|
@ -59,6 +59,7 @@ export interface DateTime extends Object {
|
||||
subtract: (amount?: DateTimeInput, unit?: DurationUnit) => DateTime;
|
||||
toDate: () => Date;
|
||||
toISOString: () => string;
|
||||
diff: (amount: DateTimeInput, unit?: DurationUnit, truncate?: boolean) => number;
|
||||
valueOf: () => number;
|
||||
unix: () => number;
|
||||
utc: () => DateTime;
|
||||
|
@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
@ -86,12 +87,13 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf
|
||||
defaultDatasource = ds.Name
|
||||
}
|
||||
|
||||
if ds.JsonData != nil {
|
||||
dsMap["jsonData"] = ds.JsonData
|
||||
} else {
|
||||
dsMap["jsonData"] = make(map[string]string)
|
||||
jsonData := ds.JsonData
|
||||
if jsonData == nil {
|
||||
jsonData = simplejson.New()
|
||||
}
|
||||
|
||||
dsMap["jsonData"] = jsonData
|
||||
|
||||
if ds.Access == m.DS_ACCESS_DIRECT {
|
||||
if ds.BasicAuth {
|
||||
dsMap["basicAuth"] = util.GetBasicAuthHeader(ds.BasicAuthUser, ds.DecryptedBasicAuthPassword())
|
||||
@ -123,7 +125,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf
|
||||
|
||||
if ds.Type == m.DS_PROMETHEUS {
|
||||
// add unproxied server URL for link to Prometheus web UI
|
||||
dsMap["directUrl"] = ds.Url
|
||||
jsonData.Set("directUrl", ds.Url)
|
||||
}
|
||||
|
||||
datasources[ds.Name] = dsMap
|
||||
|
@ -65,8 +65,6 @@ export class DatasourceSrv {
|
||||
instanceSettings: dsConfig,
|
||||
});
|
||||
|
||||
instance.id = dsConfig.id;
|
||||
instance.name = name;
|
||||
instance.components = dsPlugin.components;
|
||||
instance.meta = dsConfig.meta;
|
||||
|
||||
|
@ -9,9 +9,8 @@ import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
// import * as moment from 'moment';
|
||||
|
||||
export default class CloudWatchDatasource implements DataSourceApi<CloudWatchQuery> {
|
||||
export default class CloudWatchDatasource extends DataSourceApi<CloudWatchQuery> {
|
||||
type: any;
|
||||
name: any;
|
||||
proxyUrl: any;
|
||||
defaultRegion: any;
|
||||
standardStatistics: any;
|
||||
@ -24,8 +23,8 @@ export default class CloudWatchDatasource implements DataSourceApi<CloudWatchQue
|
||||
private templateSrv: TemplateSrv,
|
||||
private timeSrv: TimeSrv
|
||||
) {
|
||||
super(instanceSettings);
|
||||
this.type = 'cloudwatch';
|
||||
this.name = instanceSettings.name;
|
||||
this.proxyUrl = instanceSettings.url;
|
||||
this.defaultRegion = instanceSettings.jsonData.defaultRegion;
|
||||
this.instanceSettings = instanceSettings;
|
||||
|
@ -7,9 +7,7 @@ import { DataSourceApi, DataQueryRequest, DataSourceInstanceSettings } from '@gr
|
||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
|
||||
export default class Datasource implements DataSourceApi<AzureMonitorQuery, AzureDataSourceJsonData> {
|
||||
id: number;
|
||||
name: string;
|
||||
export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDataSourceJsonData> {
|
||||
azureMonitorDatasource: AzureMonitorDatasource;
|
||||
appInsightsDatasource: AppInsightsDatasource;
|
||||
azureLogAnalyticsDatasource: AzureLogAnalyticsDatasource;
|
||||
@ -21,8 +19,7 @@ export default class Datasource implements DataSourceApi<AzureMonitorQuery, Azur
|
||||
private templateSrv: TemplateSrv,
|
||||
private $q
|
||||
) {
|
||||
this.name = instanceSettings.name;
|
||||
this.id = instanceSettings.id;
|
||||
super(instanceSettings);
|
||||
this.azureMonitorDatasource = new AzureMonitorDatasource(instanceSettings, this.backendSrv, this.templateSrv);
|
||||
this.appInsightsDatasource = new AppInsightsDatasource(
|
||||
instanceSettings,
|
||||
|
@ -8,23 +8,13 @@ import {
|
||||
} from '@grafana/ui/src/types';
|
||||
import { InputQuery, InputOptions } from './types';
|
||||
|
||||
export class InputDatasource implements DataSourceApi<InputQuery, InputOptions> {
|
||||
export class InputDatasource extends DataSourceApi<InputQuery, InputOptions> {
|
||||
data: SeriesData[];
|
||||
|
||||
// Filled in by grafana plugin system
|
||||
name?: string;
|
||||
|
||||
// Filled in by grafana plugin system
|
||||
id?: number;
|
||||
|
||||
constructor(instanceSettings: DataSourceInstanceSettings<InputOptions>) {
|
||||
if (instanceSettings.jsonData) {
|
||||
this.data = instanceSettings.jsonData.data;
|
||||
}
|
||||
super(instanceSettings);
|
||||
|
||||
if (!this.data) {
|
||||
this.data = [];
|
||||
}
|
||||
this.data = instanceSettings.jsonData.data ? instanceSettings.jsonData.data : [];
|
||||
}
|
||||
|
||||
getDescription(data: SeriesData[]): string {
|
||||
|
@ -2,6 +2,8 @@ import LokiDatasource from './datasource';
|
||||
import { LokiQuery } from './types';
|
||||
import { getQueryOptions } from 'test/helpers/getQueryOptions';
|
||||
import { SeriesData } from '@grafana/ui';
|
||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
|
||||
describe('LokiDatasource', () => {
|
||||
const instanceSettings: any = {
|
||||
@ -21,14 +23,15 @@ describe('LokiDatasource', () => {
|
||||
|
||||
describe('when querying', () => {
|
||||
const backendSrvMock = { datasourceRequest: jest.fn() };
|
||||
const backendSrv = (backendSrvMock as unknown) as BackendSrv;
|
||||
|
||||
const templateSrvMock = {
|
||||
const templateSrvMock = ({
|
||||
getAdhocFilters: () => [],
|
||||
replace: a => a,
|
||||
};
|
||||
} as unknown) as TemplateSrv;
|
||||
|
||||
test('should use default max lines when no limit given', () => {
|
||||
const ds = new LokiDatasource(instanceSettings, backendSrvMock, templateSrvMock);
|
||||
const ds = new LokiDatasource(instanceSettings, backendSrv, templateSrvMock);
|
||||
backendSrvMock.datasourceRequest = jest.fn(() => Promise.resolve(testResp));
|
||||
const options = getQueryOptions<LokiQuery>({ targets: [{ expr: 'foo', refId: 'B' }] });
|
||||
|
||||
@ -41,7 +44,7 @@ describe('LokiDatasource', () => {
|
||||
test('should use custom max lines if limit is set', () => {
|
||||
const customData = { ...(instanceSettings.jsonData || {}), maxLines: 20 };
|
||||
const customSettings = { ...instanceSettings, jsonData: customData };
|
||||
const ds = new LokiDatasource(customSettings, backendSrvMock, templateSrvMock);
|
||||
const ds = new LokiDatasource(customSettings, backendSrv, templateSrvMock);
|
||||
backendSrvMock.datasourceRequest = jest.fn(() => Promise.resolve(testResp));
|
||||
|
||||
const options = getQueryOptions<LokiQuery>({ targets: [{ expr: 'foo', refId: 'B' }] });
|
||||
@ -54,7 +57,7 @@ describe('LokiDatasource', () => {
|
||||
test('should return series data', async done => {
|
||||
const customData = { ...(instanceSettings.jsonData || {}), maxLines: 20 };
|
||||
const customSettings = { ...instanceSettings, jsonData: customData };
|
||||
const ds = new LokiDatasource(customSettings, backendSrvMock, templateSrvMock);
|
||||
const ds = new LokiDatasource(customSettings, backendSrv, templateSrvMock);
|
||||
backendSrvMock.datasourceRequest = jest.fn(() => Promise.resolve(testResp));
|
||||
|
||||
const options = getQueryOptions<LokiQuery>({
|
||||
@ -77,7 +80,7 @@ describe('LokiDatasource', () => {
|
||||
|
||||
describe('and call succeeds', () => {
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
async datasourceRequest() {
|
||||
return Promise.resolve({
|
||||
status: 200,
|
||||
@ -86,8 +89,8 @@ describe('LokiDatasource', () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {});
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
|
||||
result = await ds.testDatasource();
|
||||
});
|
||||
|
||||
@ -98,7 +101,7 @@ describe('LokiDatasource', () => {
|
||||
|
||||
describe('and call fails with 401 error', () => {
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
async datasourceRequest() {
|
||||
return Promise.reject({
|
||||
statusText: 'Unauthorized',
|
||||
@ -108,8 +111,8 @@ describe('LokiDatasource', () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {});
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
|
||||
result = await ds.testDatasource();
|
||||
});
|
||||
|
||||
@ -121,7 +124,7 @@ describe('LokiDatasource', () => {
|
||||
|
||||
describe('and call fails with 404 error', () => {
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
async datasourceRequest() {
|
||||
return Promise.reject({
|
||||
statusText: 'Not found',
|
||||
@ -129,8 +132,8 @@ describe('LokiDatasource', () => {
|
||||
data: '404 page not found',
|
||||
});
|
||||
},
|
||||
};
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {});
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
|
||||
result = await ds.testDatasource();
|
||||
});
|
||||
|
||||
@ -142,7 +145,7 @@ describe('LokiDatasource', () => {
|
||||
|
||||
describe('and call fails with 502 error', () => {
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
async datasourceRequest() {
|
||||
return Promise.reject({
|
||||
statusText: 'Bad Gateway',
|
||||
@ -150,8 +153,8 @@ describe('LokiDatasource', () => {
|
||||
data: '',
|
||||
});
|
||||
},
|
||||
};
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {});
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
|
||||
result = await ds.testDatasource();
|
||||
});
|
||||
|
||||
|
@ -9,8 +9,16 @@ import { logStreamToSeriesData } from './result_transformer';
|
||||
import { formatQuery, parseQuery } from './query_utils';
|
||||
|
||||
// Types
|
||||
import { PluginMeta, DataQueryRequest, SeriesData } from '@grafana/ui/src/types';
|
||||
import { LokiQuery } from './types';
|
||||
import {
|
||||
PluginMeta,
|
||||
DataQueryRequest,
|
||||
SeriesData,
|
||||
DataSourceApi,
|
||||
DataSourceInstanceSettings,
|
||||
} from '@grafana/ui/src/types';
|
||||
import { LokiQuery, LokiOptions } from './types';
|
||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
|
||||
export const DEFAULT_MAX_LINES = 1000;
|
||||
|
||||
@ -30,12 +38,17 @@ function serializeParams(data: any) {
|
||||
.join('&');
|
||||
}
|
||||
|
||||
export class LokiDatasource {
|
||||
export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
languageProvider: LanguageProvider;
|
||||
maxLines: number;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private instanceSettings, private backendSrv, private templateSrv) {
|
||||
constructor(
|
||||
private instanceSettings: DataSourceInstanceSettings<LokiOptions>,
|
||||
private backendSrv: BackendSrv,
|
||||
private templateSrv: TemplateSrv
|
||||
) {
|
||||
super(instanceSettings);
|
||||
this.languageProvider = new LanguageProvider(this);
|
||||
const settingsData = instanceSettings.jsonData || {};
|
||||
this.maxLines = parseInt(settingsData.maxLines, 10) || DEFAULT_MAX_LINES;
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { DataQuery, Labels } from '@grafana/ui/src/types';
|
||||
import { DataQuery, Labels, DataSourceJsonData } from '@grafana/ui/src/types';
|
||||
|
||||
export interface LokiQuery extends DataQuery {
|
||||
expr: string;
|
||||
}
|
||||
|
||||
export interface LokiOptions extends DataSourceJsonData {
|
||||
maxLines?: string;
|
||||
}
|
||||
|
||||
export interface LokiLogsStream {
|
||||
labels: string;
|
||||
entries: LokiLogsStreamEntry[];
|
||||
|
@ -1,11 +1,13 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
import { DataSourceApi, DataQuery, DataQueryRequest } from '@grafana/ui';
|
||||
import { DataSourceApi, DataQuery, DataQueryRequest, DataSourceInstanceSettings } from '@grafana/ui';
|
||||
import DatasourceSrv from 'app/features/plugins/datasource_srv';
|
||||
|
||||
class MixedDatasource implements DataSourceApi<DataQuery> {
|
||||
class MixedDatasource extends DataSourceApi<DataQuery> {
|
||||
/** @ngInject */
|
||||
constructor(private datasourceSrv: DatasourceSrv) {}
|
||||
constructor(instanceSettings: DataSourceInstanceSettings, private datasourceSrv: DatasourceSrv) {
|
||||
super(instanceSettings);
|
||||
}
|
||||
|
||||
query(options: DataQueryRequest<DataQuery>) {
|
||||
const sets = _.groupBy(options.targets, 'datasource');
|
||||
|
@ -14,14 +14,15 @@ import { getQueryHints } from './query_hints';
|
||||
import { expandRecordingRules } from './language_utils';
|
||||
|
||||
// Types
|
||||
import { PromQuery } from './types';
|
||||
import { DataQueryRequest, DataSourceApi, AnnotationEvent } from '@grafana/ui/src/types';
|
||||
import { PromQuery, PromOptions } from './types';
|
||||
import { DataQueryRequest, DataSourceApi, AnnotationEvent, DataSourceInstanceSettings } from '@grafana/ui/src/types';
|
||||
import { ExploreUrlState } from 'app/types/explore';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
|
||||
export class PrometheusDatasource implements DataSourceApi<PromQuery> {
|
||||
export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions> {
|
||||
type: string;
|
||||
editorSrc: string;
|
||||
name: string;
|
||||
ruleMappings: { [index: string]: string };
|
||||
url: string;
|
||||
directUrl: string;
|
||||
@ -35,25 +36,32 @@ export class PrometheusDatasource implements DataSourceApi<PromQuery> {
|
||||
resultTransformer: ResultTransformer;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings, private $q, private backendSrv: BackendSrv, private templateSrv, private timeSrv) {
|
||||
constructor(
|
||||
instanceSettings: DataSourceInstanceSettings<PromOptions>,
|
||||
private $q,
|
||||
private backendSrv: BackendSrv,
|
||||
private templateSrv: TemplateSrv,
|
||||
private timeSrv: TimeSrv
|
||||
) {
|
||||
super(instanceSettings);
|
||||
|
||||
this.type = 'prometheus';
|
||||
this.editorSrc = 'app/features/prometheus/partials/query.editor.html';
|
||||
this.name = instanceSettings.name;
|
||||
this.url = instanceSettings.url;
|
||||
this.directUrl = instanceSettings.directUrl;
|
||||
this.basicAuth = instanceSettings.basicAuth;
|
||||
this.withCredentials = instanceSettings.withCredentials;
|
||||
this.interval = instanceSettings.jsonData.timeInterval || '15s';
|
||||
this.queryTimeout = instanceSettings.jsonData.queryTimeout;
|
||||
this.httpMethod = instanceSettings.jsonData.httpMethod || 'GET';
|
||||
this.directUrl = instanceSettings.jsonData.directUrl;
|
||||
this.resultTransformer = new ResultTransformer(templateSrv);
|
||||
this.ruleMappings = {};
|
||||
this.languageProvider = new PrometheusLanguageProvider(this);
|
||||
}
|
||||
|
||||
init() {
|
||||
init = () => {
|
||||
this.loadRules();
|
||||
}
|
||||
};
|
||||
|
||||
getQueryDisplayText(query: PromQuery) {
|
||||
return query.expr;
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { PromCompleter } from '../completer';
|
||||
import { PrometheusDatasource } from '../datasource';
|
||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||
import { DataSourceInstanceSettings } from '@grafana/ui';
|
||||
import { PromOptions } from '../types';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
jest.mock('../datasource');
|
||||
jest.mock('app/core/services/backend_srv');
|
||||
|
||||
@ -16,7 +20,13 @@ describe('Prometheus editor completer', () => {
|
||||
const editor = {};
|
||||
|
||||
const backendSrv = {} as BackendSrv;
|
||||
const datasourceStub = new PrometheusDatasource({}, {}, backendSrv, {}, {});
|
||||
const datasourceStub = new PrometheusDatasource(
|
||||
{} as DataSourceInstanceSettings<PromOptions>,
|
||||
{},
|
||||
backendSrv,
|
||||
{} as TemplateSrv,
|
||||
{} as TimeSrv
|
||||
);
|
||||
|
||||
datasourceStub.metadataRequest = jest.fn(() =>
|
||||
Promise.resolve({ data: { data: [{ metric: { job: 'node', instance: 'localhost:9100' } }] } })
|
||||
|
@ -8,6 +8,10 @@ import {
|
||||
prometheusSpecialRegexEscape,
|
||||
} from '../datasource';
|
||||
import { dateTime } from '@grafana/ui/src/utils/moment_wrapper';
|
||||
import { DataSourceInstanceSettings } from '@grafana/ui';
|
||||
import { PromOptions } from '../types';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
|
||||
jest.mock('../metric_find_query');
|
||||
|
||||
@ -18,13 +22,13 @@ const DEFAULT_TEMPLATE_SRV_MOCK = {
|
||||
|
||||
describe('PrometheusDatasource', () => {
|
||||
const ctx: any = {};
|
||||
const instanceSettings = {
|
||||
const instanceSettings = ({
|
||||
url: 'proxied',
|
||||
directUrl: 'direct',
|
||||
user: 'test',
|
||||
password: 'mupp',
|
||||
jsonData: {} as any,
|
||||
};
|
||||
} as unknown) as DataSourceInstanceSettings<PromOptions>;
|
||||
|
||||
ctx.backendSrvMock = {};
|
||||
|
||||
@ -347,27 +351,27 @@ const HOUR = 60 * MINUTE;
|
||||
const time = ({ hours = 0, seconds = 0, minutes = 0 }) => dateTime(hours * HOUR + minutes * MINUTE + seconds * SECOND);
|
||||
|
||||
const ctx = {} as any;
|
||||
const instanceSettings = {
|
||||
const instanceSettings = ({
|
||||
url: 'proxied',
|
||||
directUrl: 'direct',
|
||||
user: 'test',
|
||||
password: 'mupp',
|
||||
jsonData: { httpMethod: 'GET' },
|
||||
};
|
||||
} as unknown) as DataSourceInstanceSettings<PromOptions>;
|
||||
const backendSrv = {
|
||||
datasourceRequest: jest.fn(),
|
||||
} as any;
|
||||
|
||||
const templateSrv = {
|
||||
const templateSrv = ({
|
||||
getAdhocFilters: () => [],
|
||||
replace: jest.fn(str => str),
|
||||
};
|
||||
} as unknown) as TemplateSrv;
|
||||
|
||||
const timeSrv = {
|
||||
const timeSrv = ({
|
||||
timeRange: () => {
|
||||
return { to: { diff: () => 2000 }, from: '' };
|
||||
},
|
||||
};
|
||||
} as unknown) as TimeSrv;
|
||||
|
||||
describe('PrometheusDatasource', () => {
|
||||
describe('When querying prometheus with one target using query editor target spec', () => {
|
||||
@ -1177,13 +1181,13 @@ describe('PrometheusDatasource', () => {
|
||||
|
||||
describe('PrometheusDatasource for POST', () => {
|
||||
// const ctx = new helpers.ServiceTestContext();
|
||||
const instanceSettings = {
|
||||
const instanceSettings = ({
|
||||
url: 'proxied',
|
||||
directUrl: 'direct',
|
||||
user: 'test',
|
||||
password: 'mupp',
|
||||
jsonData: { httpMethod: 'POST' },
|
||||
};
|
||||
} as unknown) as DataSourceInstanceSettings<PromOptions>;
|
||||
|
||||
describe('When querying prometheus with one target using query editor target spec', () => {
|
||||
let results;
|
||||
|
@ -2,15 +2,17 @@ import { PrometheusDatasource } from '../datasource';
|
||||
import PrometheusMetricFindQuery from '../metric_find_query';
|
||||
import q from 'q';
|
||||
import { toUtc } from '@grafana/ui/src/utils/moment_wrapper';
|
||||
import { DataSourceInstanceSettings } from '@grafana/ui';
|
||||
import { PromOptions } from '../types';
|
||||
|
||||
describe('PrometheusMetricFindQuery', () => {
|
||||
const instanceSettings = {
|
||||
const instanceSettings = ({
|
||||
url: 'proxied',
|
||||
directUrl: 'direct',
|
||||
user: 'test',
|
||||
password: 'mupp',
|
||||
jsonData: { httpMethod: 'GET' },
|
||||
};
|
||||
} as unknown) as DataSourceInstanceSettings<PromOptions>;
|
||||
const raw = {
|
||||
from: toUtc('2018-04-25 10:00'),
|
||||
to: toUtc('2018-04-25 11:00'),
|
||||
|
@ -1,5 +1,12 @@
|
||||
import { DataQuery } from '@grafana/ui/src/types';
|
||||
import { DataQuery, DataSourceJsonData } from '@grafana/ui/src/types';
|
||||
|
||||
export interface PromQuery extends DataQuery {
|
||||
expr: string;
|
||||
}
|
||||
|
||||
export interface PromOptions extends DataSourceJsonData {
|
||||
timeInterval: string;
|
||||
queryTimeout: string;
|
||||
httpMethod: string;
|
||||
directUrl: string;
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ import { stackdriverUnitMappings } from './constants';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import _ from 'lodash';
|
||||
import StackdriverMetricFindQuery from './StackdriverMetricFindQuery';
|
||||
import { StackdriverQuery, MetricDescriptor } from './types';
|
||||
import { DataSourceApi, DataQueryRequest } from '@grafana/ui/src/types';
|
||||
import { StackdriverQuery, MetricDescriptor, StackdriverOptions } from './types';
|
||||
import { DataSourceApi, DataQueryRequest, DataSourceInstanceSettings, ScopedVars } from '@grafana/ui/src/types';
|
||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
|
||||
export default class StackdriverDatasource implements DataSourceApi<StackdriverQuery> {
|
||||
id: number;
|
||||
export default class StackdriverDatasource extends DataSourceApi<StackdriverQuery, StackdriverOptions> {
|
||||
url: string;
|
||||
baseUrl: string;
|
||||
projectName: string;
|
||||
@ -15,10 +17,15 @@ export default class StackdriverDatasource implements DataSourceApi<StackdriverQ
|
||||
metricTypes: any[];
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings, private backendSrv, private templateSrv, private timeSrv) {
|
||||
constructor(
|
||||
instanceSettings: DataSourceInstanceSettings<StackdriverOptions>,
|
||||
private backendSrv: BackendSrv,
|
||||
private templateSrv: TemplateSrv,
|
||||
private timeSrv: TimeSrv
|
||||
) {
|
||||
super(instanceSettings);
|
||||
this.baseUrl = `/stackdriver/`;
|
||||
this.url = instanceSettings.url;
|
||||
this.id = instanceSettings.id;
|
||||
this.projectName = instanceSettings.jsonData.defaultProject || '';
|
||||
this.authenticationType = instanceSettings.jsonData.authenticationType || 'jwt';
|
||||
this.metricTypes = [];
|
||||
@ -62,7 +69,7 @@ export default class StackdriverDatasource implements DataSourceApi<StackdriverQ
|
||||
}
|
||||
}
|
||||
|
||||
interpolateFilters(filters: string[], scopedVars: object) {
|
||||
interpolateFilters(filters: string[], scopedVars: ScopedVars) {
|
||||
return (filters || []).map(f => {
|
||||
return this.templateSrv.replace(f, scopedVars || {}, 'regex');
|
||||
});
|
||||
|
@ -3,26 +3,30 @@ import { metricDescriptors } from './testData';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { CustomVariable } from 'app/features/templating/all';
|
||||
import { toUtc } from '@grafana/ui/src/utils/moment_wrapper';
|
||||
import { DataSourceInstanceSettings } from '@grafana/ui';
|
||||
import { StackdriverOptions } from '../types';
|
||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
|
||||
describe('StackdriverDataSource', () => {
|
||||
const instanceSettings = {
|
||||
const instanceSettings = ({
|
||||
jsonData: {
|
||||
defaultProject: 'testproject',
|
||||
},
|
||||
};
|
||||
} as unknown) as DataSourceInstanceSettings<StackdriverOptions>;
|
||||
const templateSrv = new TemplateSrv();
|
||||
const timeSrv = {};
|
||||
const timeSrv = {} as TimeSrv;
|
||||
|
||||
describe('when performing testDataSource', () => {
|
||||
describe('and call to stackdriver api succeeds', () => {
|
||||
let ds;
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
async datasourceRequest() {
|
||||
return Promise.resolve({ status: 200 });
|
||||
},
|
||||
};
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
|
||||
result = await ds.testDatasource();
|
||||
});
|
||||
@ -35,9 +39,9 @@ describe('StackdriverDataSource', () => {
|
||||
let ds;
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
datasourceRequest: async () => Promise.resolve({ status: 200, data: metricDescriptors }),
|
||||
};
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
|
||||
result = await ds.testDatasource();
|
||||
});
|
||||
@ -50,7 +54,7 @@ describe('StackdriverDataSource', () => {
|
||||
let ds;
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
datasourceRequest: async () =>
|
||||
Promise.reject({
|
||||
statusText: 'Bad Request',
|
||||
@ -58,7 +62,7 @@ describe('StackdriverDataSource', () => {
|
||||
error: { code: 400, message: 'Field interval.endTime had an invalid value' },
|
||||
},
|
||||
}),
|
||||
};
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
|
||||
result = await ds.testDatasource();
|
||||
});
|
||||
@ -103,9 +107,9 @@ describe('StackdriverDataSource', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
datasourceRequest: async () => Promise.resolve({ status: 200, data: response }),
|
||||
};
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
|
||||
});
|
||||
|
||||
@ -122,7 +126,7 @@ describe('StackdriverDataSource', () => {
|
||||
let ds;
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
const backendSrv = {
|
||||
const backendSrv = ({
|
||||
async datasourceRequest() {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
@ -139,7 +143,7 @@ describe('StackdriverDataSource', () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
} as unknown) as BackendSrv;
|
||||
ds = new StackdriverDataSource(instanceSettings, backendSrv, templateSrv, timeSrv);
|
||||
result = await ds.getMetricTypes();
|
||||
});
|
||||
@ -155,12 +159,14 @@ describe('StackdriverDataSource', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const noopBackendSrv = ({} as unknown) as BackendSrv;
|
||||
|
||||
describe('when interpolating a template variable for the filter', () => {
|
||||
let interpolated;
|
||||
describe('and is single value variable', () => {
|
||||
beforeEach(() => {
|
||||
const filterTemplateSrv = initTemplateSrv('filtervalue1');
|
||||
const ds = new StackdriverDataSource(instanceSettings, {}, filterTemplateSrv, timeSrv);
|
||||
const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, filterTemplateSrv, timeSrv);
|
||||
interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '${test}'], {});
|
||||
});
|
||||
|
||||
@ -173,7 +179,7 @@ describe('StackdriverDataSource', () => {
|
||||
describe('and is multi value variable', () => {
|
||||
beforeEach(() => {
|
||||
const filterTemplateSrv = initTemplateSrv(['filtervalue1', 'filtervalue2'], true);
|
||||
const ds = new StackdriverDataSource(instanceSettings, {}, filterTemplateSrv, timeSrv);
|
||||
const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, filterTemplateSrv, timeSrv);
|
||||
interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '[[test]]'], {});
|
||||
});
|
||||
|
||||
@ -189,7 +195,7 @@ describe('StackdriverDataSource', () => {
|
||||
describe('and is single value variable', () => {
|
||||
beforeEach(() => {
|
||||
const groupByTemplateSrv = initTemplateSrv('groupby1');
|
||||
const ds = new StackdriverDataSource(instanceSettings, {}, groupByTemplateSrv, timeSrv);
|
||||
const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, groupByTemplateSrv, timeSrv);
|
||||
interpolated = ds.interpolateGroupBys(['[[test]]'], {});
|
||||
});
|
||||
|
||||
@ -202,7 +208,7 @@ describe('StackdriverDataSource', () => {
|
||||
describe('and is multi value variable', () => {
|
||||
beforeEach(() => {
|
||||
const groupByTemplateSrv = initTemplateSrv(['groupby1', 'groupby2'], true);
|
||||
const ds = new StackdriverDataSource(instanceSettings, {}, groupByTemplateSrv, timeSrv);
|
||||
const ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, groupByTemplateSrv, timeSrv);
|
||||
interpolated = ds.interpolateGroupBys(['[[test]]'], {});
|
||||
});
|
||||
|
||||
@ -217,7 +223,7 @@ describe('StackdriverDataSource', () => {
|
||||
describe('unit parsing', () => {
|
||||
let ds, res;
|
||||
beforeEach(() => {
|
||||
ds = new StackdriverDataSource(instanceSettings, {}, templateSrv, timeSrv);
|
||||
ds = new StackdriverDataSource(instanceSettings, noopBackendSrv, templateSrv, timeSrv);
|
||||
});
|
||||
describe('when theres only one target', () => {
|
||||
describe('and the stackdriver unit doesnt have a corresponding grafana unit', () => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DataQuery } from '@grafana/ui/src/types';
|
||||
import { DataQuery, DataSourceJsonData } from '@grafana/ui/src/types';
|
||||
|
||||
export enum MetricFindQueryTypes {
|
||||
Services = 'services',
|
||||
@ -40,6 +40,11 @@ export interface StackdriverQuery extends DataQuery {
|
||||
view?: string;
|
||||
}
|
||||
|
||||
export interface StackdriverOptions extends DataSourceJsonData {
|
||||
defaultProject?: string;
|
||||
authenticationType?: string;
|
||||
}
|
||||
|
||||
export interface AnnotationTarget {
|
||||
defaultProject: string;
|
||||
metricType: string;
|
||||
|
@ -17,13 +17,12 @@ export interface TestDataRegistry {
|
||||
[key: string]: TestData[];
|
||||
}
|
||||
|
||||
export class TestDataDatasource implements DataSourceApi<TestDataQuery> {
|
||||
id: number;
|
||||
export class TestDataDatasource extends DataSourceApi<TestDataQuery> {
|
||||
streams = new StreamHandler();
|
||||
|
||||
/** @ngInject */
|
||||
constructor(instanceSettings: DataSourceInstanceSettings) {
|
||||
this.id = instanceSettings.id;
|
||||
super(instanceSettings);
|
||||
}
|
||||
|
||||
query(options: DataQueryRequest<TestDataQuery>, observer: DataStreamObserver) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DataSourceApi, DataQueryRequest, DataQueryResponse } from '@grafana/ui';
|
||||
import { DataSourceApi, DataQueryRequest, DataQueryResponse, DataSourceInstanceSettings } from '@grafana/ui';
|
||||
|
||||
export class DatasourceSrvMock {
|
||||
constructor(private defaultDS: DataSourceApi, private datasources: { [name: string]: DataSourceApi }) {
|
||||
@ -17,14 +17,15 @@ export class DatasourceSrvMock {
|
||||
}
|
||||
}
|
||||
|
||||
export class MockDataSourceApi implements DataSourceApi {
|
||||
name: string;
|
||||
|
||||
export class MockDataSourceApi extends DataSourceApi {
|
||||
result: DataQueryResponse = { data: [] };
|
||||
queryResolver: Promise<DataQueryResponse>;
|
||||
|
||||
constructor(DataQueryResponse, name?: string) {
|
||||
this.name = name ? name : 'MockDataSourceApi';
|
||||
constructor(name?: string, result?: DataQueryResponse) {
|
||||
super({ name: name ? name : 'MockDataSourceApi' } as DataSourceInstanceSettings);
|
||||
if (result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
|
||||
query(request: DataQueryRequest): Promise<DataQueryResponse> {
|
||||
|
Loading…
Reference in New Issue
Block a user