diff --git a/.betterer.results b/.betterer.results index b1e8976a9d1..f540cfeba20 100644 --- a/.betterer.results +++ b/.betterer.results @@ -359,7 +359,7 @@ exports[`no enzyme tests`] = { "public/app/plugins/datasource/loki/configuration/ConfigEditor.test.tsx:1661240493": [ [1, 17, 13, "RegExp match", "2409514259"] ], - "public/app/plugins/datasource/loki/configuration/DebugSection.test.tsx:2317141020": [ + "public/app/plugins/datasource/loki/configuration/DebugSection.test.tsx:3844880066": [ [1, 17, 13, "RegExp match", "2409514259"] ], "public/app/plugins/datasource/loki/configuration/DerivedField.test.tsx:1527527456": [ diff --git a/packages/grafana-runtime/src/services/templateSrv.ts b/packages/grafana-runtime/src/services/templateSrv.ts index 962dacd70c2..50b40325c5c 100644 --- a/packages/grafana-runtime/src/services/templateSrv.ts +++ b/packages/grafana-runtime/src/services/templateSrv.ts @@ -17,6 +17,11 @@ export interface TemplateSrv { * Replace the values within the target string. See also {@link InterpolateFunction} */ replace(target?: string, scopedVars?: ScopedVars, format?: string | Function): string; + + /** + * Checks if a target contains template variables. + */ + containsTemplate(target?: string): boolean; } let singletonInstance: TemplateSrv; diff --git a/public/app/features/explore/utils/links.test.ts b/public/app/features/explore/utils/links.test.ts index 7d049b48197..1f58b54bcbd 100644 --- a/public/app/features/explore/utils/links.test.ts +++ b/public/app/features/explore/utils/links.test.ts @@ -22,6 +22,9 @@ describe('getFieldLinksForExplore', () => { getVariables() { return []; }, + containsTemplate() { + return false; + }, }); }); diff --git a/public/app/features/templating/template_srv.mock.ts b/public/app/features/templating/template_srv.mock.ts index 394223a75c0..4ce57cdc914 100644 --- a/public/app/features/templating/template_srv.mock.ts +++ b/public/app/features/templating/template_srv.mock.ts @@ -45,4 +45,14 @@ export class TemplateSrvMock implements TemplateSrv { } return match.slice(1).find((match) => match !== undefined); } + + containsTemplate(target: string | undefined): boolean { + if (!target) { + return false; + } + + this.regex.lastIndex = 0; + const match = this.regex.exec(target); + return match !== null; + } } diff --git a/public/app/features/templating/template_srv.test.ts b/public/app/features/templating/template_srv.test.ts index 9c42d6fbc10..ebe981efc8f 100644 --- a/public/app/features/templating/template_srv.test.ts +++ b/public/app/features/templating/template_srv.test.ts @@ -430,37 +430,37 @@ describe('templateSrv', () => { }); it('should return true if $test exists', () => { - const result = _templateSrv.variableExists('$test'); + const result = _templateSrv.containsTemplate('$test'); expect(result).toBe(true); }); it('should return true if $test exists in string', () => { - const result = _templateSrv.variableExists('something $test something'); + const result = _templateSrv.containsTemplate('something $test something'); expect(result).toBe(true); }); it('should return true if [[test]] exists in string', () => { - const result = _templateSrv.variableExists('something [[test]] something'); + const result = _templateSrv.containsTemplate('something [[test]] something'); expect(result).toBe(true); }); it('should return true if [[test:csv]] exists in string', () => { - const result = _templateSrv.variableExists('something [[test:csv]] something'); + const result = _templateSrv.containsTemplate('something [[test:csv]] something'); expect(result).toBe(true); }); it('should return true if ${test} exists in string', () => { - const result = _templateSrv.variableExists('something ${test} something'); + const result = _templateSrv.containsTemplate('something ${test} something'); expect(result).toBe(true); }); it('should return true if ${test:raw} exists in string', () => { - const result = _templateSrv.variableExists('something ${test:raw} something'); + const result = _templateSrv.containsTemplate('something ${test:raw} something'); expect(result).toBe(true); }); it('should return null if there are no variables in string', () => { - const result = _templateSrv.variableExists('string without variables'); + const result = _templateSrv.containsTemplate('string without variables'); expect(result).toBe(false); }); }); diff --git a/public/app/features/templating/template_srv.ts b/public/app/features/templating/template_srv.ts index 427cf7d6f1e..57d7671af8d 100644 --- a/public/app/features/templating/template_srv.ts +++ b/public/app/features/templating/template_srv.ts @@ -189,8 +189,11 @@ export class TemplateSrv implements BaseTemplateSrv { return variableName; } - variableExists(expression: string): boolean { - const name = this.getVariableName(expression); + containsTemplate(target: string | undefined): boolean { + if (!target) { + return false; + } + const name = this.getVariableName(target); const variable = name && this.getVariableAtIndex(name); return variable !== null && variable !== undefined; } diff --git a/public/app/plugins/datasource/cloudwatch/datasource.ts b/public/app/plugins/datasource/cloudwatch/datasource.ts index 660ca54ddfb..a4c92c98146 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.ts +++ b/public/app/plugins/datasource/cloudwatch/datasource.ts @@ -894,12 +894,12 @@ export class CloudWatchDatasource targetContainsTemplate(target: any) { return ( - this.templateSrv.variableExists(target.region) || - this.templateSrv.variableExists(target.namespace) || - this.templateSrv.variableExists(target.metricName) || - this.templateSrv.variableExists(target.expression!) || - target.logGroupNames?.some((logGroup: string) => this.templateSrv.variableExists(logGroup)) || - find(target.dimensions, (v, k) => this.templateSrv.variableExists(k) || this.templateSrv.variableExists(v)) + this.templateSrv.containsTemplate(target.region) || + this.templateSrv.containsTemplate(target.namespace) || + this.templateSrv.containsTemplate(target.metricName) || + this.templateSrv.containsTemplate(target.expression!) || + target.logGroupNames?.some((logGroup: string) => this.templateSrv.containsTemplate(logGroup)) || + find(target.dimensions, (v, k) => this.templateSrv.containsTemplate(k) || this.templateSrv.containsTemplate(v)) ); } diff --git a/public/app/plugins/datasource/elasticsearch/datasource.ts b/public/app/plugins/datasource/elasticsearch/datasource.ts index 3a797cf04d4..d9837dcf364 100644 --- a/public/app/plugins/datasource/elasticsearch/datasource.ts +++ b/public/app/plugins/datasource/elasticsearch/datasource.ts @@ -871,19 +871,19 @@ export class ElasticDatasource } targetContainsTemplate(target: any) { - if (this.templateSrv.variableExists(target.query) || this.templateSrv.variableExists(target.alias)) { + if (this.templateSrv.containsTemplate(target.query) || this.templateSrv.containsTemplate(target.alias)) { return true; } for (const bucketAgg of target.bucketAggs) { - if (this.templateSrv.variableExists(bucketAgg.field) || this.objectContainsTemplate(bucketAgg.settings)) { + if (this.templateSrv.containsTemplate(bucketAgg.field) || this.objectContainsTemplate(bucketAgg.settings)) { return true; } } for (const metric of target.metrics) { if ( - this.templateSrv.variableExists(metric.field) || + this.templateSrv.containsTemplate(metric.field) || this.objectContainsTemplate(metric.settings) || this.objectContainsTemplate(metric.meta) ) { @@ -912,7 +912,7 @@ export class ElasticDatasource for (const key of Object.keys(obj)) { if (this.isPrimitive(obj[key])) { - if (this.templateSrv.variableExists(obj[key])) { + if (this.templateSrv.containsTemplate(obj[key])) { return true; } } else if (Array.isArray(obj[key])) { diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/datasource.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/datasource.ts index 5438e82a840..71564888677 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/datasource.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/datasource.ts @@ -140,7 +140,7 @@ export default class Datasource extends DataSourceApi { getVariables() { return []; }, + containsTemplate() { + return false; + }, }); }); diff --git a/public/app/plugins/datasource/mssql/datasource.ts b/public/app/plugins/datasource/mssql/datasource.ts index d533515091a..6c65b747381 100644 --- a/public/app/plugins/datasource/mssql/datasource.ts +++ b/public/app/plugins/datasource/mssql/datasource.ts @@ -185,6 +185,6 @@ export class MssqlDatasource extends DataSourceWithBackend 0) { for (let i = 0; i < target.filters.length; i++) { - if (this.templateSrv.variableExists(target.filters[i].filter)) { + if (this.templateSrv.containsTemplate(target.filters[i].filter)) { return true; } } @@ -170,7 +170,7 @@ export default class OpenTsDatasource extends DataSourceApi 0) { for (const tagKey in target.tags) { - if (this.templateSrv.variableExists(target.tags[tagKey])) { + if (this.templateSrv.containsTemplate(target.tags[tagKey])) { return true; } } diff --git a/public/app/plugins/datasource/postgres/datasource.ts b/public/app/plugins/datasource/postgres/datasource.ts index 6d6605740d3..84d6d3a65cd 100644 --- a/public/app/plugins/datasource/postgres/datasource.ts +++ b/public/app/plugins/datasource/postgres/datasource.ts @@ -213,6 +213,6 @@ export class PostgresDatasource extends DataSourceWithBackend, start: number, end: number) => { diff --git a/public/test/specs/helpers.ts b/public/test/specs/helpers.ts index bddf0a7a0c3..1bb8a295729 100644 --- a/public/test/specs/helpers.ts +++ b/public/test/specs/helpers.ts @@ -164,7 +164,7 @@ export function TemplateSrvStub(this: any) { }; this.fillVariableValuesForUrl = () => {}; this.updateIndex = () => {}; - this.variableExists = () => { + this.containsTemplate = () => { return false; }; this.variableInitialized = () => {};