mirror of
https://github.com/grafana/grafana.git
synced 2025-08-03 01:22:29 +08:00
CloudMonitoring: Correctly interpolate multi-valued template variables in PromQL queries (#86391)
* Interpolate promql queries appropriately - Use pipes for multi-valued variables in PromQL queries - Update tests * Don't break betterer * Another any * Update public/app/plugins/datasource/cloud-monitoring/datasource.ts Co-authored-by: Andrew Hackmann <5140848+bossinc@users.noreply.github.com> --------- Co-authored-by: Andrew Hackmann <5140848+bossinc@users.noreply.github.com>
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
import { get } from 'lodash';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
|
||||
import { CustomVariableModel } from '@grafana/data';
|
||||
import { CustomVariableModel, ScopedVars } from '@grafana/data';
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
|
||||
import { createMockInstanceSetttings } from './__mocks__/cloudMonitoringInstanceSettings';
|
||||
@ -72,6 +72,33 @@ describe('Cloud Monitoring Datasource', () => {
|
||||
expect(templatedQuery[0]).toHaveProperty('datasource');
|
||||
expect(templatedQuery[0].timeSeriesList?.projectName).toEqual('project-variable');
|
||||
});
|
||||
it('should correctly apply template variables for PromQLQuery (single-value)', () => {
|
||||
const templateSrv = getTemplateSrv();
|
||||
templateSrv.replace = jest.fn().mockReturnValue('filter-variable');
|
||||
const mockInstanceSettings = createMockInstanceSetttings();
|
||||
const ds = new Datasource(mockInstanceSettings, templateSrv);
|
||||
const query = createMockQuery({ promQLQuery: { expr: '$testVar', projectName: 'test-project', step: '1' } });
|
||||
const templatedQuery = ds.interpolateVariablesInQueries([query], {});
|
||||
expect(templatedQuery[0]).toHaveProperty('datasource');
|
||||
expect(templatedQuery[0].promQLQuery?.expr).toContain('filter-variable');
|
||||
});
|
||||
it('should correctly apply template variables for PromQLQuery (multi-value)', () => {
|
||||
const templateSrv = getTemplateSrv();
|
||||
templateSrv.replace = jest
|
||||
.fn()
|
||||
.mockImplementation((_target: string, _v2: ScopedVars, formatFunction: Function) => {
|
||||
if (formatFunction) {
|
||||
return formatFunction(['filter-variable', 'filter-variable2']);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
const mockInstanceSettings = createMockInstanceSetttings();
|
||||
const ds = new Datasource(mockInstanceSettings, templateSrv);
|
||||
const query = createMockQuery({ promQLQuery: { expr: '$testVar', projectName: 'test-project', step: '1' } });
|
||||
const templatedQuery = ds.interpolateVariablesInQueries([query], {});
|
||||
expect(templatedQuery[0]).toHaveProperty('datasource');
|
||||
expect(templatedQuery[0].promQLQuery?.expr).toContain('filter-variable|filter-variable2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('migrateQuery', () => {
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
DataQueryRequest,
|
||||
DataQueryResponse,
|
||||
DataSourceInstanceSettings,
|
||||
QueryVariableModel,
|
||||
ScopedVars,
|
||||
SelectableValue,
|
||||
TimeRange,
|
||||
@ -84,7 +85,7 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend<
|
||||
),
|
||||
},
|
||||
sloQuery: sloQuery && this.interpolateProps(sloQuery, scopedVars),
|
||||
promQLQuery: promQLQuery && this.interpolateProps(promQLQuery, scopedVars),
|
||||
promQLQuery: promQLQuery && this.interpolateProps(promQLQuery, scopedVars, { expr: this.interpolatePromQLQuery }),
|
||||
};
|
||||
}
|
||||
|
||||
@ -294,11 +295,31 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend<
|
||||
return query;
|
||||
}
|
||||
|
||||
interpolateProps<T extends Record<string, any>>(object: T, scopedVars: ScopedVars = {}): T {
|
||||
interpolatePromQLQuery(value: string | string[], _variable: QueryVariableModel) {
|
||||
if (isArray(value)) {
|
||||
return value.join('|');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
interpolateProps<T extends Record<string, any>>(
|
||||
object: T,
|
||||
scopedVars: ScopedVars = {},
|
||||
formattingFunctions?: { [key: string]: Function | undefined }
|
||||
): T {
|
||||
return Object.entries(object).reduce((acc, [key, value]) => {
|
||||
let interpolatedValue = value;
|
||||
if (value && isString(value)) {
|
||||
// Pass a function to the template service for formatting
|
||||
interpolatedValue = this.templateSrv.replace(
|
||||
value,
|
||||
scopedVars,
|
||||
formattingFunctions && formattingFunctions[key]
|
||||
);
|
||||
}
|
||||
return {
|
||||
...acc,
|
||||
[key]: value && isString(value) ? this.templateSrv.replace(value, scopedVars) : value,
|
||||
[key]: interpolatedValue,
|
||||
};
|
||||
}, {} as T);
|
||||
}
|
||||
|
Reference in New Issue
Block a user