InfluxDB: Fix querying with template variables without using regex operator (#84953)

* remove regex wrappers if the operator is not a regex operator

* fix import
This commit is contained in:
ismail simsek
2024-03-22 16:14:11 +01:00
committed by GitHub
parent 65c0669f01
commit 5c146c7832
4 changed files with 42 additions and 17 deletions

View File

@@ -44,7 +44,7 @@ import InfluxQueryModel from './influx_query_model';
import InfluxSeries from './influx_series';
import { buildMetadataQuery } from './influxql_query_builder';
import { prepareAnnotation } from './migrations';
import { buildRawQuery } from './queryUtils';
import { buildRawQuery, removeRegexWrapper } from './queryUtils';
import ResponseParser from './response_parser';
import { DEFAULT_POLICY, InfluxOptions, InfluxQuery, InfluxQueryTag, InfluxVersion } from './types';
@@ -262,6 +262,11 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
if (query.tags) {
expandedQuery.tags = query.tags.map((tag) => {
// Remove the regex wrapper if the operator is not a regex operator
if (tag.operator !== '=~' && tag.operator !== '!~') {
tag.value = removeRegexWrapper(tag.value);
}
return {
...tag,
key: this.templateSrv.replace(tag.key, scopedVars),

View File

@@ -218,7 +218,10 @@ describe('InfluxDataSource Backend Mode', () => {
});
describe('variable interpolation with chained variables with backend mode', () => {
const variablesMock = [queryBuilder().withId('var1').withName('var1').withCurrent('var1').build()];
const variablesMock = [
queryBuilder().withId('var1').withName('var1').withCurrent('var1').build(),
queryBuilder().withId('path').withName('path').withCurrent('/etc/hosts').build(),
];
const mockTemplateService = new TemplateSrv({
getVariables: () => variablesMock,
getVariableWithName: (name: string) => variablesMock.filter((v) => v.name === name)[0],
@@ -309,6 +312,22 @@ describe('InfluxDataSource Backend Mode', () => {
const expected = `/^.*-var1$/`;
expect(res.tags?.[0].value).toEqual(expected);
});
it('should remove regex wrappers when operator is not a regex operator', () => {
const query: InfluxQuery = {
refId: 'A',
tags: [
{
key: 'key',
operator: '=',
value: '/^$path$/',
},
],
};
const res = ds.applyVariables(query, {});
const expected = `/etc/hosts`;
expect(res.tags?.[0].value).toEqual(expected);
});
});
describe('metric find query', () => {

View File

@@ -3,6 +3,7 @@ import { filter, find, indexOf, map } from 'lodash';
import { escapeRegex, ScopedVars } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime';
import { removeRegexWrapper } from './queryUtils';
import queryPart from './query_part';
import { DEFAULT_POLICY, InfluxQuery, InfluxQueryTag } from './types';
@@ -141,17 +142,6 @@ export default class InfluxQueryModel {
this.updatePersistedParts();
}
private removeRegexWrapper(str: string) {
const regex = /\/\^(.*?)\$\//; // match any string that starts with "/^" and ends with "$/", capturing the characters in between
const match = str.match(regex);
if (match && match.length > 1) {
return match[1];
} else {
return str;
}
}
private isOperatorTypeHandler(operator: string, value: string, fieldName: string) {
let textValue;
if (operator === 'Is Not') {
@@ -162,7 +152,7 @@ export default class InfluxQueryModel {
// Tags should always quote
if (fieldName.endsWith('::tag')) {
textValue = "'" + this.removeRegexWrapper(value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'")) + "'";
textValue = "'" + removeRegexWrapper(value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'")) + "'";
return {
operator: operator,
value: textValue,
@@ -180,7 +170,7 @@ export default class InfluxQueryModel {
textValue = lowerValue;
} else {
// String or unrecognised: quote
textValue = "'" + this.removeRegexWrapper(value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'")) + "'";
textValue = "'" + removeRegexWrapper(value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'")) + "'";
}
return {
operator: operator,
@@ -210,7 +200,7 @@ export default class InfluxQueryModel {
if (interpolate) {
value = this.templateSrv.replace(value, this.scopedVars);
}
value = this.removeRegexWrapper(value);
value = removeRegexWrapper(value);
if (operator.startsWith('Is')) {
let r = this.isOperatorTypeHandler(operator, value, tag.key);
operator = r.operator;

View File

@@ -1,7 +1,7 @@
import { cloneDeep } from 'lodash';
import InfluxQueryModel from './influx_query_model';
import { InfluxQuery } from './types';
import { InfluxQuery } from './types'; // FIXME: these functions are a beginning of a refactoring of influx_query_model.ts
// FIXME: these functions are a beginning of a refactoring of influx_query_model.ts
// into a simpler approach with full typescript types.
@@ -90,3 +90,14 @@ export function changeGroupByPart(query: InfluxQuery, partIndex: number, newPara
};
return { ...query, groupBy: newGroupBy };
}
export function removeRegexWrapper(str: string) {
const regex = /\/\^(.*?)\$\//; // match any string that starts with "/^" and ends with "$/", capturing the characters in between
const match = str.match(regex);
if (match && match.length > 1) {
return match[1];
}
return str;
}