Commit 18544211 by kay delaney Committed by GitHub

Chore: Remove angular dependency from data sources (#27735)

* Chore: Remove angular dependency from data sources

* Removes default export for time and template srvs
Also uses @grafana/runtime versions of the interfaces where possible

* Replace usage of internal templateSrv where possible

* Use runtime templateSrv in a couple more places
parent 8a5fc003
import _ from 'lodash';
import angular from 'angular';
import coreModule from '../core_module';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { dateTime } from '@grafana/data';
coreModule.filter('stringSort', () => {
......@@ -39,8 +39,7 @@ coreModule.filter('moment', () => {
};
});
/** @ngInject */
function interpolateTemplateVars(templateSrv: TemplateSrv) {
function interpolateTemplateVars(templateSrv: TemplateSrv = getTemplateSrv()) {
const filterFunc: any = (text: string, scope: any) => {
let scopedVars;
if (scope.ctrl) {
......
......@@ -3,10 +3,10 @@ import classNames from 'classnames';
import { Icon } from '@grafana/ui';
import { PanelModel } from '../../state/PanelModel';
import { DashboardModel } from '../../state/DashboardModel';
import templateSrv from 'app/features/templating/template_srv';
import appEvents from 'app/core/app_events';
import { CoreEvents } from 'app/types';
import { RowOptionsButton } from '../RowOptions/RowOptionsButton';
import { getTemplateSrv } from '@grafana/runtime';
export interface DashboardRowProps {
panel: PanelModel;
......@@ -69,7 +69,7 @@ export class DashboardRow extends React.Component<DashboardRowProps, any> {
'dashboard-row--collapsed': this.state.collapsed,
});
const title = templateSrv.replace(this.props.panel.title, this.props.panel.scopedVars, 'text');
const title = getTemplateSrv().replace(this.props.panel.title, this.props.panel.scopedVars, 'text');
const count = this.props.panel.panels ? this.props.panel.panels.length : 0;
const panels = count === 1 ? 'panel' : 'panels';
const canEdit = this.props.dashboard.meta.canEdit === true;
......
......@@ -14,9 +14,11 @@ jest.mock('app/features/dashboard/services/TimeSrv', () => ({
let fillVariableValuesForUrlMock = (params: any) => {};
jest.mock('app/features/templating/template_srv', () => ({
fillVariableValuesForUrl: (params: any) => {
fillVariableValuesForUrlMock(params);
},
getTemplateSrv: () => ({
fillVariableValuesForUrl: (params: any) => {
fillVariableValuesForUrlMock(params);
},
}),
}));
function mockLocationHref(href: string) {
......
import { config } from '@grafana/runtime';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import templateSrv from 'app/features/templating/template_srv';
import { getTemplateSrv } from 'app/features/templating/template_srv';
import { PanelModel, dateTime, urlUtil } from '@grafana/data';
export function buildParams(
......@@ -22,7 +22,7 @@ export function buildParams(
}
if (includeTemplateVars) {
templateSrv.fillVariableValuesForUrl(params);
getTemplateSrv().fillVariableValuesForUrl(params);
}
if (selectedTheme !== 'current') {
......
......@@ -2,13 +2,12 @@ import React, { Component } from 'react';
import classNames from 'classnames';
import { isEqual } from 'lodash';
import { DataLink, LoadingState, PanelData, PanelMenuItem, QueryResultMetaNotice, ScopedVars } from '@grafana/data';
import { AngularComponent } from '@grafana/runtime';
import { AngularComponent, getTemplateSrv } from '@grafana/runtime';
import { ClickOutsideWrapper, Icon, IconName, Tooltip } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors';
import PanelHeaderCorner from './PanelHeaderCorner';
import { PanelHeaderMenu } from './PanelHeaderMenu';
import templateSrv from 'app/features/templating/template_srv';
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
......@@ -137,7 +136,7 @@ export class PanelHeader extends Component<Props, State> {
render() {
const { panel, scopedVars, error, isViewing, isEditing, data, alertState } = this.props;
const { menuItems } = this.state;
const title = templateSrv.replace(panel.title, scopedVars, 'text');
const title = getTemplateSrv().replace(panel.title, scopedVars, 'text');
const panelHeaderClass = classNames({
'panel-header': true,
......
......@@ -2,10 +2,9 @@ import React, { Component } from 'react';
import { renderMarkdown, LinkModelSupplier, ScopedVars } from '@grafana/data';
import { Tooltip, PopoverContent } from '@grafana/ui';
import { getLocationSrv } from '@grafana/runtime';
import { getLocationSrv, getTemplateSrv } from '@grafana/runtime';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import templateSrv from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { InspectTab } from '../../components/Inspector/types';
......@@ -45,7 +44,7 @@ export class PanelHeaderCorner extends Component<Props> {
getInfoContent = (): JSX.Element => {
const { panel } = this.props;
const markdown = panel.description || '';
const interpolatedMarkdown = templateSrv.replace(markdown, panel.scopedVars);
const interpolatedMarkdown = getTemplateSrv().replace(markdown, panel.scopedVars);
const markedInterpolatedMarkdown = renderMarkdown(interpolatedMarkdown);
const links = this.props.links && this.props.links.getLinks(panel);
......
// Libraries
import _ from 'lodash';
// Utils
import { getTemplateSrv } from '@grafana/runtime';
import { Emitter } from 'app/core/utils/emitter';
import { getNextRefIdChar } from 'app/core/utils/query';
import templateSrv from 'app/features/templating/template_srv';
// Types
import {
AppEvent,
......@@ -478,7 +478,7 @@ export class PanelModel implements DataConfigSource {
if (extraVars) {
vars = vars ? { ...vars, ...extraVars } : extraVars;
}
return templateSrv.replace(value, vars, format);
return getTemplateSrv().replace(value, vars, format);
}
resendLastResult() {
......
......@@ -4,8 +4,8 @@ import { ReplaySubject, Unsubscribable, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
// Services & Utils
import { getTemplateSrv } from '@grafana/runtime';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import templateSrv from 'app/features/templating/template_srv';
import { runRequest, preProcessPanelData } from './runRequest';
import { runSharedRequest, isSharedDashboardQuery } from '../../../plugins/datasource/dashboard';
......@@ -164,7 +164,7 @@ export class PanelQueryRunner {
return query;
});
const lowerIntervalLimit = minInterval ? templateSrv.replace(minInterval, request.scopedVars) : ds.interval;
const lowerIntervalLimit = minInterval ? getTemplateSrv().replace(minInterval, request.scopedVars) : ds.interval;
const norm = rangeUtil.calculateInterval(timeRange, maxDataPoints, lowerIntervalLimit);
// make shallow copy of scoped vars,
......
......@@ -14,7 +14,7 @@ import appEvents from 'app/core/app_events';
import config from 'app/core/config';
// Services
import templateSrv from 'app/features/templating/template_srv';
import { getTemplateSrv } from '@grafana/runtime';
// Constants
import { LS_PANEL_COPY_KEY, PANEL_BORDER } from 'app/core/constants';
......@@ -84,7 +84,7 @@ export function applyPanelTimeOverrides(panel: PanelModel, timeRange: TimeRange)
};
if (panel.timeFrom) {
const timeFromInterpolated = templateSrv.replace(panel.timeFrom, panel.scopedVars);
const timeFromInterpolated = getTemplateSrv().replace(panel.timeFrom, panel.scopedVars);
const timeFromInfo = rangeUtil.describeTextRange(timeFromInterpolated);
if (timeFromInfo.invalid) {
newTimeData.timeInfo = 'invalid time override';
......@@ -106,7 +106,7 @@ export function applyPanelTimeOverrides(panel: PanelModel, timeRange: TimeRange)
}
if (panel.timeShift) {
const timeShiftInterpolated = templateSrv.replace(panel.timeShift, panel.scopedVars);
const timeShiftInterpolated = getTemplateSrv().replace(panel.timeShift, panel.scopedVars);
const timeShiftInfo = rangeUtil.describeTextRange(timeShiftInterpolated);
if (timeShiftInfo.invalid) {
newTimeData.timeInfo = 'invalid timeshift';
......
import _ from 'lodash';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import templateSrv, { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import coreModule from 'app/core/core_module';
import { getConfig } from 'app/core/config';
import {
......@@ -80,11 +80,13 @@ const buildLabelPath = (label: string) => {
};
export const getPanelLinksVariableSuggestions = (): VariableSuggestion[] => [
...templateSrv.getVariables().map(variable => ({
value: variable.name as string,
label: variable.name,
origin: VariableOrigin.Template,
})),
...getTemplateSrv()
.getVariables()
.map(variable => ({
value: variable.name as string,
label: variable.name,
origin: VariableOrigin.Template,
})),
{
value: `${DataLinkBuiltInVars.includeVars}`,
label: 'All variables',
......@@ -240,11 +242,13 @@ export const getPanelOptionsVariableSuggestions = (plugin: PanelPlugin, data?: D
const dataVariables = plugin.meta.skipDataQuery ? [] : getDataFrameVars(data || []);
return [
...dataVariables, // field values
...templateSrv.getVariables().map(variable => ({
value: variable.name as string,
label: variable.name,
origin: VariableOrigin.Template,
})),
...getTemplateSrv()
.getVariables()
.map(variable => ({
value: variable.name as string,
label: variable.name,
origin: VariableOrigin.Template,
})),
];
};
......
......@@ -4,11 +4,14 @@ import coreModule from 'app/core/core_module';
// Services & Utils
import config from 'app/core/config';
import { importDataSourcePlugin } from './plugin_loader';
import { DataSourceSrv as DataSourceService, getDataSourceSrv as getDataSourceService } from '@grafana/runtime';
import {
DataSourceSrv as DataSourceService,
getDataSourceSrv as getDataSourceService,
TemplateSrv,
} from '@grafana/runtime';
// Types
import { AppEvents, DataSourceApi, DataSourceInstanceSettings, DataSourceSelectItem, ScopedVars } from '@grafana/data';
import { auto } from 'angular';
import { TemplateSrv } from '../templating/template_srv';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
// Pretend Datasource
import { expressionDatasource } from 'app/features/expressions/ExpressionDatasource';
......
......@@ -4,7 +4,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import DefaultVariableQueryEditor from '../variables/editor/DefaultVariableQueryEditor';
import { DataSourcePluginMeta } from '@grafana/data';
import { TemplateSrv } from '../templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
async function loadComponent(meta: DataSourcePluginMeta) {
const dsPlugin = await importDataSourcePlugin(meta);
......
import coreModule from 'app/core/core_module';
import templateSrv from './template_srv';
import { getTemplateSrv } from './template_srv';
coreModule.factory('templateSrv', () => templateSrv);
coreModule.factory('templateSrv', () => getTemplateSrv());
......@@ -336,4 +336,4 @@ export class TemplateSrv implements BaseTemplateSrv {
// Expose the template srv
const srv = new TemplateSrv();
setTemplateSrv(srv);
export default srv;
export const getTemplateSrv = () => srv;
......@@ -6,7 +6,7 @@ import { DataSourceSelectItem, stringToJsRegex } from '@grafana/data';
import { getDatasourceSrv } from '../../plugins/datasource_srv';
import { getVariable } from '../state/selectors';
import { DataSourceVariableModel } from '../types';
import templateSrv from '../../templating/template_srv';
import { getTemplateSrv } from '@grafana/runtime';
import _ from 'lodash';
import { changeVariableEditorExtended } from '../editor/reducer';
......@@ -23,7 +23,7 @@ export const updateDataSourceVariableOptions = (
let regex;
if (variableInState.regex) {
regex = templateSrv.replace(variableInState.regex, undefined, 'regex');
regex = getTemplateSrv().replace(variableInState.regex, undefined, 'regex');
regex = stringToJsRegex(regex);
}
......
......@@ -7,7 +7,7 @@ import { validateVariableSelectionState } from '../state/actions';
import { getVariable } from '../state/selectors';
import { IntervalVariableModel } from '../types';
import { getTimeSrv } from '../../dashboard/services/TimeSrv';
import templateSrv from '../../templating/template_srv';
import { getTemplateSrv, TemplateSrv } from '../../templating/template_srv';
import appEvents from '../../../core/app_events';
export interface UpdateIntervalVariableOptionsDependencies {
......@@ -30,7 +30,7 @@ export const updateIntervalVariableOptions = (
export interface UpdateAutoValueDependencies {
calculateInterval: typeof rangeUtil.calculateInterval;
getTimeSrv: typeof getTimeSrv;
templateSrv: typeof templateSrv;
templateSrv: TemplateSrv;
}
export const updateAutoValue = (
......@@ -38,7 +38,7 @@ export const updateAutoValue = (
dependencies: UpdateAutoValueDependencies = {
calculateInterval: rangeUtil.calculateInterval,
getTimeSrv: getTimeSrv,
templateSrv: templateSrv,
templateSrv: getTemplateSrv(),
}
): ThunkResult<void> => (dispatch, getState) => {
const variableInState = getVariable<IntervalVariableModel>(identifier.id, getState());
......
......@@ -2,7 +2,7 @@ import React, { ChangeEvent, PureComponent } from 'react';
import { InlineFormLabel, LegacyForms } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors';
import templateSrv from '../../templating/template_srv';
import { getTemplateSrv } from '@grafana/runtime';
import { SelectionOptionsEditor } from '../editor/SelectionOptionsEditor';
import { QueryVariableModel, VariableRefresh, VariableSort, VariableWithMultiSupport } from '../types';
import { QueryVariableEditorState } from './reducer';
......@@ -185,7 +185,7 @@ export class QueryVariableEditorUnConnected extends PureComponent<Props, State>
<VariableQueryEditor
datasource={this.props.editor.extended?.dataSource}
query={this.props.variable.query}
templateSrv={templateSrv}
templateSrv={getTemplateSrv()}
onChange={this.onQueryChange}
/>
)}
......
import { AppEvents, DataSourcePluginMeta, DataSourceSelectItem } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { validateVariableSelectionState } from '../state/actions';
import { QueryVariableModel, VariableRefresh } from '../types';
import { ThunkResult } from '../../../types';
import { getDatasourceSrv } from '../../plugins/datasource_srv';
import templateSrv from '../../templating/template_srv';
import { getTimeSrv } from '../../dashboard/services/TimeSrv';
import appEvents from '../../../core/app_events';
import { importDataSourcePlugin } from '../../plugins/plugin_loader';
......@@ -138,5 +138,5 @@ const getTemplatedRegex = (variable: QueryVariableModel): string => {
return '';
}
return templateSrv.replace(variable.regex, {}, 'regex');
return getTemplateSrv().replace(variable.regex, {}, 'regex');
};
......@@ -30,7 +30,7 @@ import {
import { toVariableIdentifier, toVariablePayload, VariableIdentifier } from './types';
import { appEvents } from 'app/core/core';
import { contextSrv } from 'app/core/services/context_srv';
import templateSrv from '../../templating/template_srv';
import { getTemplateSrv, TemplateSrv } from '../../templating/template_srv';
import { alignCurrentWithMulti } from '../shared/multiOptions';
import { isMulti } from '../guard';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
......@@ -89,7 +89,7 @@ export const initDashboardTemplating = (list: VariableModel[]): ThunkResult<void
dispatch(addVariable(toVariablePayload(model, { global: false, index: orderIndex++, model })));
}
templateSrv.updateTimeRange(getTimeSrv().timeRange());
getTemplateSrv().updateTimeRange(getTimeSrv().timeRange());
for (let index = 0; index < getVariables(getState()).length; index++) {
dispatch(addInitLock(toVariablePayload(getVariables(getState())[index])));
......@@ -458,13 +458,13 @@ export const variableUpdated = (
};
export interface OnTimeRangeUpdatedDependencies {
templateSrv: typeof templateSrv;
templateSrv: TemplateSrv;
appEvents: typeof appEvents;
}
export const onTimeRangeUpdated = (
timeRange: TimeRange,
dependencies: OnTimeRangeUpdatedDependencies = { templateSrv: templateSrv, appEvents: appEvents }
dependencies: OnTimeRangeUpdatedDependencies = { templateSrv: getTemplateSrv(), appEvents: appEvents }
): ThunkResult<Promise<void>> => async (dispatch, getState) => {
dependencies.templateSrv.updateTimeRange(timeRange);
const variablesThatNeedRefresh = getVariables(getState()).filter(variable => {
......
import { TemplateSrv } from 'app/features/templating/template_srv';
import { AnnotationTarget } from './types';
export class CloudMonitoringAnnotationsQueryCtrl {
static templateUrl = 'partials/annotations.editor.html';
annotation: any;
templateSrv: TemplateSrv;
/** @ngInject */
constructor() {
this.annotation.target = this.annotation.target || {};
this.onQueryChange = this.onQueryChange.bind(this);
......
import React, { FC } from 'react';
import _ from 'lodash';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { SelectableValue, rangeUtil } from '@grafana/data';
import { Segment } from '@grafana/ui';
import { alignmentPeriods, alignOptions } from '../constants';
......
......@@ -2,7 +2,7 @@ import React from 'react';
import { LegacyForms } from '@grafana/ui';
const { Input } = LegacyForms;
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { SelectableValue } from '@grafana/data';
import CloudMonitoringDatasource from '../datasource';
......
import React, { useEffect, useState } from 'react';
import _ from 'lodash';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { SelectableValue } from '@grafana/data';
import CloudMonitoringDatasource from '../datasource';
import { Segment } from '@grafana/ui';
......
......@@ -9,8 +9,8 @@ import {
SelectableValue,
toDataFrame,
} from '@grafana/data';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import {
CloudMonitoringQuery,
......@@ -28,11 +28,10 @@ export default class CloudMonitoringDatasource extends DataSourceApi<CloudMonito
api: API;
authenticationType: string;
/** @ngInject */
constructor(
private instanceSettings: DataSourceInstanceSettings<CloudMonitoringOptions>,
public templateSrv: TemplateSrv,
private timeSrv: TimeSrv
public templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
super(instanceSettings);
this.authenticationType = instanceSettings.jsonData.authenticationType || 'jwt';
......
......@@ -2,7 +2,7 @@ import _ from 'lodash';
import { alignOptions, aggOptions, ValueTypes, MetricKind, systemLabels } from './constants';
import { SelectableValue } from '@grafana/data';
import CloudMonitoringDatasource from './datasource';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { MetricDescriptor, Filter, MetricQuery } from './types';
export const extractServicesFromMetricDescriptors = (metricDescriptors: MetricDescriptor[]) =>
......
......@@ -21,8 +21,8 @@ import {
DataQueryErrorType,
} from '@grafana/data';
import { getBackendSrv, toDataQueryResponse } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { ThrottlingErrorMessage } from './components/ThrottlingErrorMessage';
import memoizedDebounce from './memoizedDebounce';
import {
......@@ -83,11 +83,10 @@ export class CloudWatchDatasource extends DataSourceApi<CloudWatchQuery, CloudWa
logQueries: Record<string, { id: string; region: string; statsQuery: boolean }>;
languageProvider: CloudWatchLanguageProvider;
/** @ngInject */
constructor(
instanceSettings: DataSourceInstanceSettings<CloudWatchJsonData>,
private templateSrv: TemplateSrv,
private timeSrv: TimeSrv
private readonly templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
super(instanceSettings);
this.type = 'cloudwatch';
......
import angular from 'angular';
import coreModule from 'app/core/core_module';
import _ from 'lodash';
import { TemplateSrv } from 'app/features/templating/template_srv';
import DatasourceSrv from 'app/features/plugins/datasource_srv';
import { TemplateSrv } from '@grafana/runtime';
export class CloudWatchQueryParameterCtrl {
/** @ngInject */
constructor($scope: any, templateSrv: TemplateSrv, uiSegmentSrv: any, datasourceSrv: DatasourceSrv) {
constructor($scope: any, templateSrv: TemplateSrv, uiSegmentSrv: any) {
$scope.init = () => {
const target = $scope.target;
target.namespace = target.namespace || '';
......
......@@ -18,8 +18,8 @@ import { ElasticQueryBuilder } from './query_builder';
import { toUtc } from '@grafana/data';
import * as queryDef from './query_def';
import { getBackendSrv } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { DataLinkConfig, ElasticsearchOptions, ElasticsearchQuery } from './types';
// Those are metadata fields as defined in https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-fields.html#_identity_metadata_fields.
......@@ -53,11 +53,10 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
dataLinks: DataLinkConfig[];
languageProvider: LanguageProvider;
/** @ngInject */
constructor(
instanceSettings: DataSourceInstanceSettings<ElasticsearchOptions>,
private templateSrv: TemplateSrv,
private timeSrv: TimeSrv
private readonly templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
super(instanceSettings);
this.basicAuth = instanceSettings.basicAuth;
......
......@@ -4,27 +4,21 @@ import { ElasticDatasource } from './datasource';
import { DataSourceInstanceSettings, dateTime } from '@grafana/data';
import { ElasticsearchOptions } from './types';
import { TemplateSrv } from '../../../features/templating/template_srv';
import { getTimeSrv, TimeSrv } from '../../../features/dashboard/services/TimeSrv';
import { getTemplateSrv } from '@grafana/runtime';
import { TimeSrv } from '../../../features/dashboard/services/TimeSrv';
jest.mock('app/features/templating/template_srv', () => {
return {
getAdhocFilters: jest.fn(() => [] as any[]),
replace: jest.fn((a: string) => a),
};
});
const templateSrvStub = {
getAdhocFilters: jest.fn(() => [] as any[]),
replace: jest.fn((a: string) => a),
} as any;
jest.mock('app/features/dashboard/services/TimeSrv', () => ({
__esModule: true,
getTimeSrv: jest.fn().mockReturnValue({
timeRange(): any {
return {
from: dateTime(1531468681),
to: dateTime(1531489712),
};
},
}),
}));
const timeSrvStub = {
timeRange(): any {
return {
from: dateTime(1531468681),
to: dateTime(1531489712),
};
},
} as any;
const dataSource = new ElasticDatasource(
{
......@@ -36,8 +30,8 @@ const dataSource = new ElasticDatasource(
timeField: '@time',
},
} as DataSourceInstanceSettings<ElasticsearchOptions>,
getTemplateSrv() as TemplateSrv,
getTimeSrv() as TimeSrv
templateSrvStub as TemplateSrv,
timeSrvStub as TimeSrv
);
describe('transform prometheus query to elasticsearch query', () => {
it('Prometheus query with exact equals labels ( 2 labels ) and metric __name__', () => {
......
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
export class AzureMonitorAnnotationsQueryCtrl {
static templateUrl = 'partials/annotations.editor.html';
......@@ -10,8 +10,7 @@ export class AzureMonitorAnnotationsQueryCtrl {
defaultQuery =
'<your table>\n| where $__timeFilter() \n| project TimeGenerated, Text=YourTitleColumn, Tags="tag1,tag2"';
/** @ngInject */
constructor(private templateSrv: TemplateSrv) {
constructor(private templateSrv: TemplateSrv = getTemplateSrv()) {
this.annotation.queryType = this.annotation.queryType || 'Azure Log Analytics';
this.annotation.rawQuery = this.annotation.rawQuery || this.defaultQuery;
this.initDropdowns();
......
......@@ -4,7 +4,7 @@ import { QueryCtrl } from 'app/plugins/sdk';
import TimegrainConverter from './time_grain_converter';
import './editor/editor_component';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { auto, IPromise } from 'angular';
import { DataFrame, PanelEvents, rangeUtil } from '@grafana/data';
import { AzureQueryType, AzureMetricQuery } from './types';
......
......@@ -7,11 +7,6 @@ import { GrafanaQuery, GrafanaAnnotationQuery, GrafanaAnnotationType } from './t
jest.mock('@grafana/runtime', () => ({
...((jest.requireActual('@grafana/runtime') as unknown) as object),
getBackendSrv: () => backendSrv,
getTemplateSrv: () => ({
replace: (val: string) => {
return val.replace('$var2', 'replaced__delimiter__replaced2').replace('$var', 'replaced');
},
}),
}));
describe('grafana data source', () => {
......@@ -30,7 +25,13 @@ describe('grafana data source', () => {
return Promise.resolve([]);
});
ds = new GrafanaDatasource({} as DataSourceInstanceSettings);
const templateSrvStub = {
replace: (val: string) => {
return val.replace('$var2', 'replaced__delimiter__replaced2').replace('$var', 'replaced');
},
};
ds = new GrafanaDatasource({} as DataSourceInstanceSettings, templateSrvStub as any);
});
describe('with tags that have template variables', () => {
......
import _ from 'lodash';
import {
AnnotationEvent,
AnnotationQueryRequest,
......@@ -8,12 +9,15 @@ import {
} from '@grafana/data';
import { GrafanaQuery, GrafanaAnnotationQuery, GrafanaAnnotationType } from './types';
import { getBackendSrv, getTemplateSrv, toDataQueryResponse } from '@grafana/runtime';
import { getBackendSrv, getTemplateSrv, TemplateSrv, toDataQueryResponse } from '@grafana/runtime';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
export class GrafanaDatasource extends DataSourceApi<GrafanaQuery> {
constructor(instanceSettings: DataSourceInstanceSettings) {
constructor(
instanceSettings: DataSourceInstanceSettings,
private readonly templateSrv: TemplateSrv = getTemplateSrv()
) {
super(instanceSettings);
}
......@@ -50,7 +54,6 @@ export class GrafanaDatasource extends DataSourceApi<GrafanaQuery> {
}
annotationQuery(options: AnnotationQueryRequest<GrafanaQuery>): Promise<AnnotationEvent[]> {
const templateSrv = getTemplateSrv();
const annotation = (options.annotation as unknown) as GrafanaAnnotationQuery;
const params: any = {
from: options.range.from.valueOf(),
......@@ -77,7 +80,7 @@ export class GrafanaDatasource extends DataSourceApi<GrafanaQuery> {
const delimiter = '__delimiter__';
const tags = [];
for (const t of params.tags) {
const renderedValues = templateSrv.replace(t, {}, (value: any) => {
const renderedValues = this.templateSrv.replace(t, {}, (value: any) => {
if (typeof value === 'string') {
return value;
}
......
......@@ -13,7 +13,7 @@ import {
import { isVersionGtOrEq, SemVersion } from 'app/core/utils/version';
import gfunc from './gfunc';
import { getBackendSrv } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
// Types
import { GraphiteOptions, GraphiteQuery, GraphiteType, MetricTankRequestMeta } from './types';
import { getRollupNotice, getRuntimeConsolidationNotice } from 'app/plugins/datasource/graphite/meta';
......@@ -33,8 +33,7 @@ export class GraphiteDatasource extends DataSourceApi<GraphiteQuery, GraphiteOpt
funcDefsPromise: Promise<any> | null = null;
_seriesRefLetters: string;
/** @ngInject */
constructor(instanceSettings: any, private templateSrv: TemplateSrv) {
constructor(instanceSettings: any, private readonly templateSrv: TemplateSrv = getTemplateSrv()) {
super(instanceSettings);
this.basicAuth = instanceSettings.basicAuth;
this.url = instanceSettings.url;
......
import _ from 'lodash';
import { Parser } from './parser';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { ScopedVars } from '@grafana/data';
export default class GraphiteQuery {
......
......@@ -7,7 +7,7 @@ import { QueryCtrl } from 'app/plugins/sdk';
import appEvents from 'app/core/app_events';
import { promiseToDigest } from 'app/core/utils/promiseToDigest';
import { auto } from 'angular';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { AppEvents } from '@grafana/data';
const GRAPHITE_TAG_OPERATORS = ['=', '!=', '=~', '!=~'];
......
......@@ -4,7 +4,7 @@ import { ButtonCascader, CascaderOption } from '@grafana/ui';
import InfluxQueryModel from '../influx_query_model';
import { AdHocFilterField, KeyValuePair } from 'app/features/explore/AdHocFilterField';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import InfluxDatasource from '../datasource';
import { InfluxQueryBuilder } from '../query_builder';
import { InfluxOptions, InfluxQuery } from '../types';
......@@ -48,7 +48,7 @@ function getChooserText({ measurement, field, error }: ChooserOptions): string {
}
export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
templateSrv: TemplateSrv = new TemplateSrv();
templateSrv: TemplateSrv = getTemplateSrv();
state: State = {
measurements: [],
measurement: null,
......
......@@ -19,7 +19,8 @@ import InfluxQueryModel from './influx_query_model';
import ResponseParser from './response_parser';
import { InfluxQueryBuilder } from './query_builder';
import { InfluxQuery, InfluxOptions, InfluxVersion } from './types';
import { getBackendSrv, getTemplateSrv, DataSourceWithBackend, frameToMetricFindValue } from '@grafana/runtime';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getBackendSrv, DataSourceWithBackend, frameToMetricFindValue } from '@grafana/runtime';
import { Observable, from } from 'rxjs';
import { FluxQueryEditor } from './components/FluxQueryEditor';
......@@ -37,7 +38,10 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
httpMode: string;
isFlux: boolean;
constructor(instanceSettings: DataSourceInstanceSettings<InfluxOptions>) {
constructor(
instanceSettings: DataSourceInstanceSettings<InfluxOptions>,
private readonly templateSrv: TemplateSrv = getTemplateSrv()
) {
super(instanceSettings);
this.type = 'influxdb';
......@@ -97,7 +101,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
applyTemplateVariables(query: InfluxQuery, scopedVars: ScopedVars): Record<string, any> {
return {
...query,
query: getTemplateSrv().replace(query.query ?? '', scopedVars), // The raw query text
query: this.templateSrv.replace(query.query ?? '', scopedVars), // The raw query text
};
}
......@@ -111,7 +115,6 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
const queryTargets: any[] = [];
let i, y;
const templateSrv = getTemplateSrv();
let allQueries = _.map(targets, target => {
if (target.hide) {
......@@ -123,7 +126,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
// backward compatibility
scopedVars.interval = scopedVars.__interval;
return new InfluxQueryModel(target, templateSrv, scopedVars).render(true);
return new InfluxQueryModel(target, this.templateSrv, scopedVars).render(true);
}).reduce((acc, current) => {
if (current !== '') {
acc += ';' + current;
......@@ -136,9 +139,9 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
}
// add global adhoc filters to timeFilter
const adhocFilters = (templateSrv as any).getAdhocFilters(this.name);
const adhocFilters = this.templateSrv.getAdhocFilters(this.name);
if (adhocFilters.length > 0) {
const tmpQuery = new InfluxQueryModel({ refId: 'A' }, templateSrv, scopedVars);
const tmpQuery = new InfluxQueryModel({ refId: 'A' }, this.templateSrv, scopedVars);
timeFilter += ' AND ' + tmpQuery.renderAdhocFilters(adhocFilters);
}
......@@ -146,7 +149,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
scopedVars.timeFilter = { value: timeFilter };
// replace templated variables
allQueries = templateSrv.replace(allQueries, scopedVars);
allQueries = this.templateSrv.replace(allQueries, scopedVars);
return this._seriesQuery(allQueries, options).then((data: any): any => {
if (!data || !data.results) {
......@@ -163,7 +166,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
const target = queryTargets[i];
let alias = target.alias;
if (alias) {
alias = templateSrv.replace(target.alias, options.scopedVars);
alias = this.templateSrv.replace(target.alias, options.scopedVars);
}
const meta: QueryResultMeta = {
......@@ -214,7 +217,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
const timeFilter = this.getTimeFilter({ rangeRaw: options.rangeRaw, timezone: options.dashboard.timezone });
let query = options.annotation.query.replace('$timeFilter', timeFilter);
query = getTemplateSrv().replace(query, undefined, 'regex');
query = this.templateSrv.replace(query, undefined, 'regex');
return this._seriesQuery(query, options).then((data: any) => {
if (!data || !data.results || !data.results[0]) {
......@@ -228,18 +231,16 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
}
targetContainsTemplate(target: any) {
const templateSrv = getTemplateSrv() as any; // :(
for (const group of target.groupBy) {
for (const param of group.params) {
if (templateSrv.variableExists(param)) {
if (this.templateSrv.variableExists(param)) {
return true;
}
}
}
for (const i in target.tags) {
if (templateSrv.variableExists(target.tags[i].value)) {
if (this.templateSrv.variableExists(target.tags[i].value)) {
return true;
}
}
......@@ -254,25 +255,23 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
let expandedQueries = queries;
if (queries && queries.length > 0) {
const templateSrv = getTemplateSrv();
expandedQueries = queries.map(query => {
const expandedQuery = {
...query,
datasource: this.name,
measurement: templateSrv.replace(query.measurement ?? '', scopedVars, 'regex'),
policy: templateSrv.replace(query.policy ?? '', scopedVars, 'regex'),
measurement: this.templateSrv.replace(query.measurement ?? '', scopedVars, 'regex'),
policy: this.templateSrv.replace(query.policy ?? '', scopedVars, 'regex'),
};
if (query.rawQuery) {
expandedQuery.query = templateSrv.replace(query.query ?? '', scopedVars, 'regex');
expandedQuery.query = this.templateSrv.replace(query.query ?? '', scopedVars, 'regex');
}
if (query.tags) {
const expandedTags = query.tags.map(tag => {
const expandedTag = {
...tag,
value: templateSrv.replace(tag.value, undefined, 'regex'),
value: this.templateSrv.replace(tag.value, undefined, 'regex'),
};
return expandedTag;
});
......@@ -304,7 +303,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
});
}
const interpolated = getTemplateSrv().replace(query, undefined, 'regex');
const interpolated = this.templateSrv.replace(query, undefined, 'regex');
return this._seriesQuery(interpolated, options).then(resp => {
return this.responseParser.parse(query, resp);
......
......@@ -4,7 +4,7 @@ import { InfluxQueryBuilder } from './query_builder';
import InfluxQueryModel from './influx_query_model';
import queryPart from './query_part';
import { QueryCtrl } from 'app/plugins/sdk';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { InfluxQuery } from './types';
import InfluxDatasource from './datasource';
......
......@@ -9,7 +9,6 @@ const templateSrv = new TemplateSrvStub();
jest.mock('@grafana/runtime', () => ({
...((jest.requireActual('@grafana/runtime') as unknown) as object),
getBackendSrv: () => backendSrv,
getTemplateSrv: () => templateSrv,
}));
describe('InfluxDataSource', () => {
......@@ -22,7 +21,7 @@ describe('InfluxDataSource', () => {
beforeEach(() => {
jest.clearAllMocks();
ctx.instanceSettings.url = '/api/datasources/proxy/1';
ctx.ds = new InfluxDatasource(ctx.instanceSettings);
ctx.ds = new InfluxDatasource(ctx.instanceSettings, templateSrv);
});
describe('When issuing metricFindQuery', () => {
......@@ -124,7 +123,7 @@ describe('InfluxDataSource', () => {
beforeEach(() => {
ctx.instanceSettings.url = '/api/datasources/proxy/1';
ctx.ds = new InfluxDatasource(ctx.instanceSettings);
ctx.ds = new InfluxDatasource(ctx.instanceSettings, templateSrv);
});
describe('When issuing metricFindQuery', () => {
......
......@@ -13,7 +13,7 @@ import { getBackendSrv, BackendSrvRequest } from '@grafana/runtime';
import { Observable, from, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { serializeParams } from 'app/core/utils/fetch';
export type JaegerQuery = {
......@@ -21,7 +21,7 @@ export type JaegerQuery = {
} & DataQuery;
export class JaegerDatasource extends DataSourceApi<JaegerQuery> {
constructor(private instanceSettings: DataSourceInstanceSettings) {
constructor(private instanceSettings: DataSourceInstanceSettings, private readonly timeSrv: TimeSrv = getTimeSrv()) {
super(instanceSettings);
}
......@@ -81,7 +81,7 @@ export class JaegerDatasource extends DataSourceApi<JaegerQuery> {
}
getTimeRange(): { start: number; end: number } {
const range = getTimeSrv().timeRange();
const range = this.timeSrv.timeRange();
return {
start: getTime(range.from, false),
end: getTime(range.to, true),
......
......@@ -21,16 +21,12 @@ jest.mock('@grafana/runtime', () => ({
getBackendSrv: () => backendSrv,
}));
jest.mock('app/features/dashboard/services/TimeSrv', () => {
return {
getTimeSrv: () => ({
timeRange: () => ({
from: new Date(0),
to: new Date(1),
}),
}),
};
});
const timeSrvStub = {
timeRange: () => ({
from: new Date(0),
to: new Date(1),
}),
};
describe('LokiDatasource', () => {
let fetchStream: Subject<FetchResponse>;
......@@ -120,7 +116,7 @@ describe('LokiDatasource', () => {
replace: (a: string) => a,
} as unknown) as TemplateSrv;
const ds = new LokiDatasource(settings, templateSrvMock);
const ds = new LokiDatasource(settings, templateSrvMock, timeSrvStub as any);
const options = getQueryOptions<LokiQuery>({ targets: [{ expr: 'foo', refId: 'B', maxLines: maxDataPoints }] });
......@@ -515,7 +511,7 @@ function createLokiDSForTests(
const customData = { ...(instanceSettings.jsonData || {}), maxLines: 20 };
const customSettings = { ...instanceSettings, jsonData: customData };
return new LokiDatasource(customSettings, templateSrvMock);
return new LokiDatasource(customSettings, templateSrvMock, timeSrvStub as any);
}
function makeAnnotationQueryRequest(): AnnotationQueryRequest<LokiQuery> {
......
......@@ -24,13 +24,12 @@ import {
ScopedVars,
TimeRange,
} from '@grafana/data';
import { BackendSrvRequest, FetchError, getBackendSrv } from '@grafana/runtime';
import { getTemplateSrv, TemplateSrv, BackendSrvRequest, FetchError, getBackendSrv } from '@grafana/runtime';
import { addLabelToQuery } from 'app/plugins/datasource/prometheus/add_label_to_query';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { convertToWebSocketUrl } from 'app/core/utils/explore';
import { lokiResultsToTableModel, lokiStreamResultToDataFrame, processRangeQueryResponse } from './result_transformer';
import { getHighlighterExpressionsFromQuery } from './query_utils';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import {
LokiOptions,
......@@ -63,8 +62,11 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
languageProvider: LanguageProvider;
maxLines: number;
/** @ngInject */
constructor(private instanceSettings: DataSourceInstanceSettings<LokiOptions>, private templateSrv: TemplateSrv) {
constructor(
private instanceSettings: DataSourceInstanceSettings<LokiOptions>,
private readonly templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
super(instanceSettings);
this.languageProvider = new LanguageProvider(this);
......@@ -294,7 +296,7 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
const labelNamesRegex = /^label_names\(\)\s*$/;
const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]*)\)\s*$/;
const timeRange = range || getTimeSrv().timeRange();
const timeRange = range || this.timeSrv.timeRange();
const params = rangeToParams({ from: timeRange.from.valueOf(), to: timeRange.to.valueOf() });
const labelNames = query.match(labelNamesRegex);
......
......@@ -2,6 +2,8 @@ import { CircularDataFrame, FieldCache, FieldType, MutableDataFrame } from '@gra
import { LokiStreamResult, LokiTailResponse, LokiStreamResponse, LokiResultType, TransformerOptions } from './types';
import * as ResultTransformer from './result_transformer';
import { enhanceDataFrame } from './result_transformer';
import { setTemplateSrv } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
const streamResult: LokiStreamResult[] = [
{
......@@ -32,6 +34,10 @@ const lokiResponse: LokiStreamResponse = {
};
describe('loki result transformer', () => {
beforeAll(() => {
setTemplateSrv(new TemplateSrv());
});
afterAll(() => {
jest.restoreAllMocks();
});
......
......@@ -19,7 +19,7 @@ import {
ScopedVars,
} from '@grafana/data';
import templateSrv from 'app/features/templating/template_srv';
import { getTemplateSrv } from '@grafana/runtime';
import TableModel from 'app/core/table_model';
import { formatQuery, getHighlighterExpressionsFromQuery } from './query_utils';
import {
......@@ -245,7 +245,7 @@ export function createMetricLabel(labelData: { [key: string]: string }, options?
let label =
options === undefined || _.isEmpty(options.legendFormat)
? getOriginalMetricName(labelData)
: renderTemplate(templateSrv.replace(options.legendFormat ?? '', options.scopedVars), labelData);
: renderTemplate(getTemplateSrv().replace(options.legendFormat ?? '', options.scopedVars), labelData);
if (!label && options) {
label = options.query;
......
......@@ -2,8 +2,8 @@ import _ from 'lodash';
import ResponseParser from './response_parser';
import { getBackendSrv } from '@grafana/runtime';
import { ScopedVars } from '@grafana/data';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
//Types
import { MssqlQueryForInterpolation } from './types';
......@@ -13,8 +13,11 @@ export class MssqlDatasource {
responseParser: ResponseParser;
interval: string;
/** @ngInject */
constructor(instanceSettings: any, private templateSrv: TemplateSrv, private timeSrv: TimeSrv) {
constructor(
instanceSettings: any,
private readonly templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
this.name = instanceSettings.name;
this.id = instanceSettings.id;
this.responseParser = new ResponseParser();
......
......@@ -3,12 +3,11 @@ import { Observable, of } from 'rxjs';
import { catchError, map, mapTo } from 'rxjs/operators';
import { getBackendSrv } from '@grafana/runtime';
import { ScopedVars } from '@grafana/data';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import MysqlQuery from 'app/plugins/datasource/mysql/mysql_query';
import ResponseParser, { MysqlResponse } from './response_parser';
import { MysqlMetricFindValue, MysqlQueryForInterpolation } from './types';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getSearchFilterScopedVar } from '../../../features/variables/utils';
export class MysqlDatasource {
......@@ -18,8 +17,11 @@ export class MysqlDatasource {
queryModel: MysqlQuery;
interval: string;
/** @ngInject */
constructor(instanceSettings: any, private templateSrv: TemplateSrv, private timeSrv: TimeSrv) {
constructor(
instanceSettings: any,
private readonly templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
this.name = instanceSettings.name;
this.id = instanceSettings.id;
this.responseParser = new ResponseParser();
......
import _ from 'lodash';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { ScopedVars } from '@grafana/data';
export default class MysqlQuery {
......
......@@ -6,11 +6,10 @@ import { SqlPart } from 'app/core/components/sql_part/sql_part';
import MysqlQuery from './mysql_query';
import sqlPart from './sql_part';
import { auto } from 'angular';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { CoreEvents } from 'app/types';
import { PanelEvents } from '@grafana/data';
import { VariableWithMultiSupport } from 'app/features/variables/types';
import { getLocationSrv } from '@grafana/runtime';
import { getLocationSrv, TemplateSrv } from '@grafana/runtime';
export interface QueryMeta {
sql: string;
......
......@@ -2,7 +2,7 @@ import angular from 'angular';
import _ from 'lodash';
import { dateMath, DataQueryRequest, DataSourceApi, ScopedVars } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { OpenTsdbOptions, OpenTsdbQuery } from './types';
export default class OpenTsDatasource extends DataSourceApi<OpenTsdbQuery, OpenTsdbOptions> {
......@@ -19,8 +19,7 @@ export default class OpenTsDatasource extends DataSourceApi<OpenTsdbQuery, OpenT
aggregatorsPromise: any;
filterTypesPromise: any;
/** @ngInject */
constructor(instanceSettings: any, private templateSrv: TemplateSrv) {
constructor(instanceSettings: any, private readonly templateSrv: TemplateSrv = getTemplateSrv()) {
super(instanceSettings);
this.type = 'opentsdb';
this.url = instanceSettings.url;
......
......@@ -6,8 +6,8 @@ import { DataQueryResponse, ScopedVars } from '@grafana/data';
import ResponseParser from './response_parser';
import PostgresQuery from 'app/plugins/datasource/postgres/postgres_query';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
//Types
import { PostgresMetricFindValue, PostgresQueryForInterpolation } from './types';
import { getSearchFilterScopedVar } from '../../../features/variables/utils';
......@@ -20,11 +20,10 @@ export class PostgresDatasource {
queryModel: PostgresQuery;
interval: string;
/** @ngInject */
constructor(
instanceSettings: { name: any; id?: any; jsonData?: any },
private templateSrv: TemplateSrv,
private timeSrv: TimeSrv
private readonly templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
this.name = instanceSettings.name;
this.id = instanceSettings.id;
......
import _ from 'lodash';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrv } from '@grafana/runtime';
import { ScopedVars } from '@grafana/data';
export default class PostgresQuery {
......
......@@ -6,11 +6,10 @@ import { SqlPart } from 'app/core/components/sql_part/sql_part';
import PostgresQuery from './postgres_query';
import sqlPart from './sql_part';
import { auto } from 'angular';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { CoreEvents } from 'app/types';
import { PanelEvents } from '@grafana/data';
import { VariableWithMultiSupport } from 'app/features/variables/types';
import { getLocationSrv } from '@grafana/runtime';
import { getLocationSrv, TemplateSrv } from '@grafana/runtime';
export interface QueryMeta {
sql: string;
......
......@@ -15,8 +15,8 @@ import {
} from '@grafana/data';
import { BackendSrvRequest, FetchError, getBackendSrv } from '@grafana/runtime';
import { safeStringifyValue } from 'app/core/utils/explore';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import templateSrv from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import cloneDeep from 'lodash/cloneDeep';
import defaults from 'lodash/defaults';
import LRU from 'lru-cache';
......@@ -58,7 +58,11 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
lookupsDisabled: boolean;
customQueryParameters: any;
constructor(instanceSettings: DataSourceInstanceSettings<PromOptions>) {
constructor(
instanceSettings: DataSourceInstanceSettings<PromOptions>,
private readonly templateSrv: TemplateSrv = getTemplateSrv(),
private readonly timeSrv: TimeSrv = getTimeSrv()
) {
super(instanceSettings);
this.type = 'prometheus';
......@@ -150,7 +154,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
}
targetContainsTemplate(target: PromQuery) {
return templateSrv.variableExists(target.expr);
return this.templateSrv.variableExists(target.expr);
}
prepareTargets = (options: DataQueryRequest<PromQuery>, start: number, end: number) => {
......@@ -313,12 +317,12 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
let interval: number = rangeUtil.intervalToSeconds(options.interval);
// Minimum interval ("Min step"), if specified for the query, or same as interval otherwise.
const minInterval = rangeUtil.intervalToSeconds(
templateSrv.replace(target.interval || options.interval, options.scopedVars)
this.templateSrv.replace(target.interval || options.interval, options.scopedVars)
);
// Scrape interval as specified for the query ("Min step") or otherwise taken from the datasource.
// Min step field can have template variables in it, make sure to replace it.
const scrapeInterval = target.interval
? rangeUtil.intervalToSeconds(templateSrv.replace(target.interval, options.scopedVars))
? rangeUtil.intervalToSeconds(this.templateSrv.replace(target.interval, options.scopedVars))
: rangeUtil.intervalToSeconds(this.interval);
const intervalFactor = target.intervalFactor || 1;
......@@ -344,7 +348,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
let expr = target.expr;
// Apply adhoc filters
const adhocFilters = templateSrv.getAdhocFilters(this.name);
const adhocFilters = this.templateSrv.getAdhocFilters(this.name);
expr = adhocFilters.reduce((acc: string, filter: { key?: any; operator?: any; value?: any }) => {
const { key, operator } = filter;
let { value } = filter;
......@@ -355,18 +359,11 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
}, expr);
// Only replace vars in expression after having (possibly) updated interval vars
query.expr = templateSrv.replace(expr, scopedVars, this.interpolateQueryExpr);
query.expr = this.templateSrv.replace(expr, scopedVars, this.interpolateQueryExpr);
// Align query interval with step to allow query caching and to ensure
// that about-same-time query results look the same.
const adjusted = alignRange(
start,
end,
query.step,
getTimeSrv()
.timeRange()
.to.utcOffset() * 60
);
const adjusted = alignRange(start, end, query.step, this.timeSrv.timeRange().to.utcOffset() * 60);
query.start = adjusted.start;
query.end = adjusted.end;
this._addTracingHeaders(query, options);
......@@ -495,14 +492,14 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
const scopedVars = {
__interval: { text: this.interval, value: this.interval },
__interval_ms: { text: rangeUtil.intervalToMs(this.interval), value: rangeUtil.intervalToMs(this.interval) },
...this.getRangeScopedVars(getTimeSrv().timeRange()),
...this.getRangeScopedVars(this.timeSrv.timeRange()),
};
const interpolated = templateSrv.replace(query, scopedVars, this.interpolateQueryExpr);
const interpolated = this.templateSrv.replace(query, scopedVars, this.interpolateQueryExpr);
const metricFindQuery = new PrometheusMetricFindQuery(this, interpolated);
return metricFindQuery.process();
}
getRangeScopedVars(range: TimeRange = getTimeSrv().timeRange()) {
getRangeScopedVars(range: TimeRange = this.timeSrv.timeRange()) {
const msRange = range.to.diff(range.from);
const sRange = Math.round(msRange / 1000);
return {
......@@ -639,7 +636,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
const expandedQuery = {
...query,
datasource: this.name,
expr: templateSrv.replace(query.expr, scopedVars, this.interpolateQueryExpr),
expr: this.templateSrv.replace(query.expr, scopedVars, this.interpolateQueryExpr),
};
return expandedQuery;
});
......@@ -709,7 +706,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
}
getTimeRange(): { start: number; end: number } {
const range = getTimeSrv().timeRange();
const range = this.timeSrv.timeRange();
return {
start: this.getPrometheusTime(range.from, false),
end: this.getPrometheusTime(range.to, true),
......
......@@ -8,13 +8,6 @@ import { backendSrv } from 'app/core/services/backend_srv'; // will use the vers
import { PromOptions } from './types';
import { FetchResponse } from '@grafana/runtime';
jest.mock('app/features/templating/template_srv', () => {
return {
getAdhocFilters: jest.fn(() => [] as any[]),
replace: jest.fn((a: string) => a),
};
});
jest.mock('@grafana/runtime', () => ({
...((jest.requireActual('@grafana/runtime') as unknown) as object),
getBackendSrv: () => backendSrv,
......@@ -47,6 +40,11 @@ jest.mock('app/features/dashboard/services/TimeSrv', () => ({
}),
}));
const templateSrvStub = {
getAdhocFilters: jest.fn(() => [] as any[]),
replace: jest.fn((a: string) => a),
} as any;
beforeEach(() => {
jest.clearAllMocks();
});
......@@ -54,7 +52,7 @@ beforeEach(() => {
describe('PrometheusMetricFindQuery', () => {
let ds: PrometheusDatasource;
beforeEach(() => {
ds = new PrometheusDatasource(instanceSettings);
ds = new PrometheusDatasource(instanceSettings, templateSrvStub);
});
const setupMetricFindQuery = (data: any) => {
......
......@@ -10,7 +10,7 @@ import {
TIME_SERIES_VALUE_FIELD_NAME,
} from '@grafana/data';
import { FetchResponse } from '@grafana/runtime';
import templateSrv from 'app/features/templating/template_srv';
import { getTemplateSrv } from 'app/features/templating/template_srv';
import {
isMatrixData,
MatrixOrVectorResult,
......@@ -231,7 +231,7 @@ function getValueField(
function createLabelInfo(labels: { [key: string]: string }, options: TransformOptions) {
if (options?.legendFormat) {
const title = renderTemplate(templateSrv.replace(options.legendFormat, options?.scopedVars), labels);
const title = renderTemplate(getTemplateSrv().replace(options.legendFormat, options?.scopedVars), labels);
return { name: title, labels };
}
......
......@@ -19,18 +19,20 @@ import {
AnnotationEvent,
} from '@grafana/data';
import { Scenario, TestDataQuery } from './types';
import { getBackendSrv, toDataQueryError } from '@grafana/runtime';
import { getBackendSrv, toDataQueryError, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import { queryMetricTree } from './metricTree';
import { from, merge, Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { runStream } from './runStreams';
import templateSrv from 'app/features/templating/template_srv';
import { getSearchFilterScopedVar } from 'app/features/variables/utils';
type TestData = TimeSeries | TableData;
export class TestDataDataSource extends DataSourceApi<TestDataQuery> {
constructor(instanceSettings: DataSourceInstanceSettings) {
constructor(
instanceSettings: DataSourceInstanceSettings,
private readonly templateSrv: TemplateSrv = getTemplateSrv()
) {
super(instanceSettings);
}
......@@ -63,7 +65,7 @@ export class TestDataDataSource extends DataSourceApi<TestDataQuery> {
intervalMs: options.intervalMs,
maxDataPoints: options.maxDataPoints,
datasourceId: this.id,
alias: templateSrv.replace(target.alias || '', options.scopedVars),
alias: this.templateSrv.replace(target.alias || '', options.scopedVars),
});
}
}
......@@ -173,7 +175,7 @@ export class TestDataDataSource extends DataSourceApi<TestDataQuery> {
metricFindQuery(query: string, options: any) {
return new Promise<MetricFindValue[]>((resolve, reject) => {
setTimeout(() => {
const interpolatedQuery = templateSrv.replace(
const interpolatedQuery = this.templateSrv.replace(
query,
getSearchFilterScopedVar({ query, wildcardChar: '*', options })
);
......
......@@ -14,7 +14,7 @@ import {
dateTimeFormatISO,
dateTimeFormat,
} from '@grafana/data';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import { ColumnRender, TableRenderModel, ColumnStyle } from './types';
import { ColumnOptionsCtrl } from './column_options';
......@@ -27,7 +27,7 @@ export class TableRenderer {
private table: TableRenderModel,
private timeZone: TimeZone,
private sanitize: (v: any) => any,
private templateSrv: TemplateSrv,
private templateSrv: TemplateSrv = getTemplateSrv(),
private theme?: GrafanaThemeType
) {
this.initColumns();
......
import { PluginMeta } from '@grafana/data';
import { PanelPlugin } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime';
export interface PluginDashboard {
dashboardId: number;
......@@ -34,5 +35,5 @@ export interface VariableQueryProps {
query: any;
onChange: (query: any, definition: string) => void;
datasource: any;
templateSrv: any;
templateSrv: TemplateSrv;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment