Commit 31ad86ff by Hugo Häggmark Committed by GitHub

TemplateSrv: deprecates templateSrv.variables and adds getVariables (#23026)

* TemplateSrv: deprecates templateSrv.variables and adds getVariables

* Update public/app/plugins/datasource/postgres/query_ctrl.ts

Co-Authored-By: Dominik Prokop <dominik.prokop@grafana.com>

* Update public/app/plugins/datasource/stackdriver/components/VariableQueryEditor.test.tsx

Co-Authored-By: Dominik Prokop <dominik.prokop@grafana.com>

* Update public/app/plugins/datasource/cloudwatch/datasource.ts

Co-Authored-By: Dominik Prokop <dominik.prokop@grafana.com>

* Update public/app/plugins/datasource/mysql/query_ctrl.ts

Co-Authored-By: Dominik Prokop <dominik.prokop@grafana.com>

* Chore: updates after PR comments

Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
parent 441e87d4
......@@ -95,7 +95,7 @@ export function uiSegmentSrv(this: any, $sce: any, templateSrv: any) {
});
if (addTemplateVars) {
_.each(templateSrv.variables, variable => {
_.each(templateSrv.getVariables(), variable => {
if (variableTypeFilter === void 0 || variableTypeFilter === variable.type) {
segments.unshift(self.newSegment({ type: 'value', value: '$' + variable.name, expandable: true }));
}
......
......@@ -8,16 +8,16 @@ import { getConfig } from 'app/core/config';
import locationUtil from 'app/core/utils/location_util';
import { DataLinkBuiltInVars } from '@grafana/ui';
import {
DataFrame,
DataLink,
KeyValue,
deprecationWarning,
Field,
FieldType,
KeyValue,
LinkModel,
DataFrame,
ScopedVars,
FieldType,
Field,
VariableSuggestion,
VariableOrigin,
VariableSuggestion,
VariableSuggestionsScope,
} from '@grafana/data';
......@@ -77,7 +77,7 @@ const buildLabelPath = (label: string) => {
};
export const getPanelLinksVariableSuggestions = (): VariableSuggestion[] => [
...templateSrv.variables.map(variable => ({
...templateSrv.getVariables().map(variable => ({
value: variable.name as string,
label: variable.name,
origin: VariableOrigin.Template,
......
// Libraries
import sortBy from 'lodash/sortBy';
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';
// Types
import { DataSourceApi, DataSourceSelectItem, ScopedVars, AppEvents } from '@grafana/data';
import { AppEvents, DataSourceApi, 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';
import { DataSourceVariableModel } from '../templating/types';
export class DatasourceSrv implements DataSourceService {
datasources: Record<string, DataSourceApi> = {};
......@@ -163,11 +161,13 @@ export class DatasourceSrv implements DataSourceService {
addDataSourceVariables(list: any[]) {
// look for data source variables
this.templateSrv.variables
this.templateSrv
.getVariables()
.filter(variable => variable.type === 'datasource')
.forEach(variable => {
.forEach((variable: DataSourceVariableModel) => {
const first = variable.current.value === 'default' ? config.defaultDatasource : variable.current.value;
const ds = config.datasources[first];
const index = (first as unknown) as string;
const ds = config.datasources[index];
if (ds) {
const key = `$${variable.name}`;
......
import config from 'app/core/config';
import 'app/features/plugins/datasource_srv';
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import { PluginMeta, DataSourcePluginMeta } from '@grafana/data';
import { DataSourcePluginMeta, PluginMeta } from '@grafana/data';
// Datasource variable $datasource with current value 'BBB'
const templateSrv: any = {
variables: [
getVariables: () => [
{
type: 'datasource',
name: 'datasource',
......
import kbn from 'app/core/utils/kbn';
import _ from 'lodash';
import { escapeHtml } from 'app/core/utils/text';
import { ScopedVars, TimeRange } from '@grafana/data';
import { getVariableWithName, getFilteredVariables } from '../variables/state/selectors';
import { deprecationWarning, ScopedVars, TimeRange } from '@grafana/data';
import { getFilteredVariables, getVariableClones, getVariableWithName } from '../variables/state/selectors';
import { getConfig } from 'app/core/config';
import { variableRegex } from './utils';
import { isAdHoc } from '../variables/guard';
import { VariableModel } from './types';
function luceneEscape(value: string) {
return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, '\\$1');
......@@ -16,8 +17,7 @@ interface FieldAccessorCache {
}
export class TemplateSrv {
variables: any[];
private _variables: any[];
private regex = variableRegex;
private index: any = {};
private grafanaVariables: any = {};
......@@ -28,11 +28,11 @@ export class TemplateSrv {
constructor() {
this.builtIns['__interval'] = { text: '1s', value: '1s' };
this.builtIns['__interval_ms'] = { text: '100', value: '100' };
this.variables = [];
this._variables = [];
}
init(variables: any, timeRange?: TimeRange) {
this.variables = variables;
this._variables = variables;
this.timeRange = timeRange;
this.updateIndex();
}
......@@ -41,10 +41,28 @@ export class TemplateSrv {
return this.builtIns.__interval.value;
}
/**
* @deprecated: this instance variable should not be used and will be removed in future releases
*
* Use getVariables function instead
*/
get variables(): any[] {
deprecationWarning('template_srv.ts', 'variables', 'getVariables');
return this.getVariables();
}
getVariables(): VariableModel[] {
if (getConfig().featureToggles.newVariables) {
return getVariableClones();
}
return this._variables;
}
updateIndex() {
const existsOrEmpty = (value: any) => value || value === '';
this.index = this.variables.reduce((acc, currentValue) => {
this.index = this._variables.reduce((acc, currentValue) => {
if (currentValue.current && (currentValue.current.isNone || existsOrEmpty(currentValue.current.value))) {
acc[currentValue.name] = currentValue;
}
......@@ -345,7 +363,7 @@ export class TemplateSrv {
}
fillVariableValuesForUrl(params: any, scopedVars?: ScopedVars) {
_.each(this.variables, variable => {
_.each(this._variables, variable => {
if (scopedVars && scopedVars[variable.name] !== void 0) {
if (scopedVars[variable.name].skipUrlSync) {
return;
......@@ -387,8 +405,8 @@ export class TemplateSrv {
if (getConfig().featureToggles.newVariables) {
return getFilteredVariables(isAdHoc);
}
if (Array.isArray(this.variables)) {
return this.variables.filter(isAdHoc);
if (Array.isArray(this._variables)) {
return this._variables.filter(isAdHoc);
}
return [];
};
......
......@@ -7,20 +7,21 @@ import { AppNotificationTimeout } from 'app/types';
import { store } from 'app/store/store';
import kbn from 'app/core/utils/kbn';
import {
DataQueryRequest,
DataSourceApi,
DataSourceInstanceSettings,
dateMath,
ScopedVars,
toDataFrame,
TimeRange,
DataSourceApi,
DataQueryRequest,
DataSourceInstanceSettings,
toDataFrame,
} from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { ThrottlingErrorMessage } from './components/ThrottlingErrorMessage';
import memoizedDebounce from './memoizedDebounce';
import { CloudWatchQuery, CloudWatchJsonData } from './types';
import { CloudWatchJsonData, CloudWatchQuery } from './types';
import { VariableWithMultiSupport } from 'app/features/templating/types';
const displayAlert = (datasourceName: string, region: string) =>
store.dispatch(
......@@ -121,7 +122,7 @@ export default class CloudWatchDatasource extends DataSourceApi<CloudWatchQuery,
}
get variables() {
return this.templateSrv.variables.map(v => `$${v.name}`);
return this.templateSrv.getVariables().map(v => `$${v.name}`);
}
getPeriod(target: any, options: any) {
......@@ -562,9 +563,11 @@ export default class CloudWatchDatasource extends DataSourceApi<CloudWatchQuery,
return { ...result, [key]: value };
}
const valueVar = this.templateSrv.variables.find(({ name }) => name === this.templateSrv.getVariableName(value));
const valueVar = this.templateSrv
.getVariables()
.find(({ name }) => name === this.templateSrv.getVariableName(value));
if (valueVar) {
if (valueVar.multi) {
if (((valueVar as unknown) as VariableWithMultiSupport).multi) {
const values = this.templateSrv.replace(value, scopedVars, 'pipe').split('|');
return { ...result, [key]: values };
}
......@@ -577,8 +580,10 @@ export default class CloudWatchDatasource extends DataSourceApi<CloudWatchQuery,
replace(target: string, scopedVars: ScopedVars, displayErrorIfIsMultiTemplateVariable?: boolean, fieldName?: string) {
if (displayErrorIfIsMultiTemplateVariable) {
const variable = this.templateSrv.variables.find(({ name }) => name === this.templateSrv.getVariableName(target));
if (variable && variable.multi) {
const variable = this.templateSrv
.getVariables()
.find(({ name }) => name === this.templateSrv.getVariableName(target));
if (variable && ((variable as unknown) as VariableWithMultiSupport).multi) {
this.debouncedCustomAlert(
'CloudWatch templating error',
`Multi template variables are not supported for ${fieldName || target}`
......
......@@ -207,7 +207,7 @@ export class CloudWatchQueryParameterCtrl {
});
if (addTemplateVars) {
_.each(templateSrv.variables, variable => {
_.each(templateSrv.getVariables(), variable => {
segments.unshift(
uiSegmentSrv.newSegment({
type: 'template',
......
......@@ -74,6 +74,6 @@ export class AzureMonitorAnnotationsQueryCtrl {
};
get templateVariables() {
return this.templateSrv.variables.map((t: any) => '$' + t.name);
return this.templateSrv.getVariables().map((t: any) => '$' + t.name);
}
}
......@@ -7,8 +7,7 @@ import kbn from 'app/core/utils/kbn';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { auto, IPromise } from 'angular';
import { DataFrame } from '@grafana/data';
import { PanelEvents } from '@grafana/data';
import { DataFrame, PanelEvents } from '@grafana/data';
export interface ResultFormat {
text: string;
......@@ -570,7 +569,7 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
};
get templateVariables() {
return this.templateSrv.variables.map(t => '$' + t.name);
return this.templateSrv.getVariables().map(t => '$' + t.name);
}
/* Application Insights Section */
......
......@@ -158,7 +158,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
}
// add template variables
_.eachRight(this.templateSrv.variables, variable => {
_.eachRight(this.templateSrv.getVariables(), variable => {
altSegments.unshift(
this.uiSegmentSrv.newSegment({
type: 'template',
......@@ -369,7 +369,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
return this.datasource.getTagValuesAutoComplete(tagExpressions, tagKey, valuePrefix).then((values: any[]) => {
const altValues = _.map(values, 'text');
// Add template variables as additional values
_.eachRight(this.templateSrv.variables, variable => {
_.eachRight(this.templateSrv.getVariables(), variable => {
altValues.push('${' + variable.name + ':regex}');
});
return mapToDropdownOptions(altValues);
......
......@@ -267,7 +267,7 @@ export class InfluxQueryCtrl extends QueryCtrl {
});
if (addTemplateVars) {
for (const variable of this.templateSrv.variables) {
for (const variable of this.templateSrv.getVariables()) {
segments.unshift(
this.uiSegmentSrv.newSegment({
type: 'value',
......
......@@ -9,6 +9,7 @@ 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/templating/types';
export interface QueryMeta {
sql: string;
......@@ -301,10 +302,10 @@ export class MysqlQueryCtrl extends QueryCtrl {
});
if (config.addTemplateVars) {
for (const variable of this.templateSrv.variables) {
for (const variable of this.templateSrv.getVariables()) {
let value;
value = '$' + variable.name;
if (config.templateQuoter && variable.multi === false) {
if (config.templateQuoter && ((variable as unknown) as VariableWithMultiSupport).multi === false) {
value = config.templateQuoter(value);
}
......
......@@ -9,6 +9,7 @@ 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/templating/types';
export interface QueryMeta {
sql: string;
......@@ -333,10 +334,10 @@ export class PostgresQueryCtrl extends QueryCtrl {
});
if (config.addTemplateVars) {
for (const variable of this.templateSrv.variables) {
for (const variable of this.templateSrv.getVariables()) {
let value;
value = '$' + variable.name;
if (config.templateQuoter && variable.multi === false) {
if (config.templateQuoter && ((variable as unknown) as VariableWithMultiSupport).multi === false) {
value = config.templateQuoter(value);
}
......
......@@ -4,6 +4,7 @@ import renderer from 'react-test-renderer';
import { StackdriverVariableQueryEditor } from './VariableQueryEditor';
import { VariableQueryProps } from 'app/types/plugins';
import { MetricFindQueryTypes } from '../types';
import { VariableModel } from 'app/features/templating/types';
jest.mock('../functions', () => ({
getMetricTypes: (): any => ({ metricTypes: [], selectedMetricType: '' }),
......@@ -18,7 +19,7 @@ const props: VariableQueryProps = {
getProjects: async (): Promise<any[]> => [],
getMetricTypes: async (p: any): Promise<any[]> => [],
},
templateSrv: { replace: (s: string) => s, variables: [] },
templateSrv: { replace: (s: string) => s, getVariables: () => ([] as unknown) as VariableModel[] },
};
describe('VariableQueryEditor', () => {
......
import React, { PureComponent } from 'react';
import { VariableQueryProps } from 'app/types/plugins';
import { SimpleSelect } from './';
import { getMetricTypes, getLabelKeys, extractServicesFromMetricDescriptors } from '../functions';
import { extractServicesFromMetricDescriptors, getLabelKeys, getMetricTypes } from '../functions';
import { MetricFindQueryTypes, VariableQueryData } from '../types';
export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryProps, VariableQueryData> {
......@@ -143,7 +143,7 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
}
insertTemplateVariables(options: any) {
const templateVariables = this.props.templateSrv.variables.map((v: any) => ({
const templateVariables = this.props.templateSrv.getVariables().map((v: any) => ({
name: `$${v.name}`,
value: `$${v.name}`,
}));
......
......@@ -2,13 +2,13 @@ import { stackdriverUnitMappings } from './constants';
import appEvents from 'app/core/app_events';
import _ from 'lodash';
import StackdriverMetricFindQuery from './StackdriverMetricFindQuery';
import { StackdriverQuery, MetricDescriptor, StackdriverOptions, Filter, VariableQueryData } from './types';
import { Filter, MetricDescriptor, StackdriverOptions, StackdriverQuery, VariableQueryData } from './types';
import {
DataSourceApi,
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
ScopedVars,
DataQueryResponse,
} from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
......@@ -38,7 +38,7 @@ export default class StackdriverDatasource extends DataSourceApi<StackdriverQuer
}
get variables() {
return this.templateSrv.variables.map(v => `$${v.name}`);
return this.templateSrv.getVariables().map(v => `$${v.name}`);
}
async getTimeSeries(options: DataQueryRequest<StackdriverQuery>) {
......
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