Chore: Use TemplateSrv from @grafana/runtime in influxdb datasource (#87813)
use templatesrv from @grafana/runtime
This commit is contained in:
@@ -1,32 +1,23 @@
|
|||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
import { AdHocVariableFilter, DataSourceInstanceSettings, PluginType, ScopedVars } from '@grafana/data';
|
import { DataSourceInstanceSettings, PluginType, ScopedVars } from '@grafana/data';
|
||||||
import { FetchResponse, getBackendSrv, setBackendSrv, VariableInterpolation } from '@grafana/runtime';
|
import { FetchResponse, getBackendSrv, setBackendSrv, TemplateSrv, VariableInterpolation } from '@grafana/runtime';
|
||||||
|
|
||||||
import { TemplateSrv } from '../../../../features/templating/template_srv';
|
|
||||||
import InfluxDatasource from '../datasource';
|
import InfluxDatasource from '../datasource';
|
||||||
import { InfluxOptions, InfluxVersion } from '../types';
|
import { InfluxOptions, InfluxVersion } from '../types';
|
||||||
|
|
||||||
const getAdhocFiltersMock = jest.fn().mockImplementation(() => []);
|
export const replaceMock = jest.fn().mockImplementation((a: string, ...rest: unknown[]) => a);
|
||||||
const replaceMock = jest.fn().mockImplementation((a: string, ...rest: unknown[]) => a);
|
export const templateSrvStub = mockTemplateSrv(replaceMock);
|
||||||
|
|
||||||
export const templateSrvStub = {
|
|
||||||
getAdhocFilters: getAdhocFiltersMock,
|
|
||||||
replace: replaceMock,
|
|
||||||
} as unknown as TemplateSrv;
|
|
||||||
|
|
||||||
export function mockTemplateSrv(
|
export function mockTemplateSrv(
|
||||||
getAdhocFiltersMock: (datasourceName: string) => AdHocVariableFilter[],
|
rm: (
|
||||||
replaceMock: (
|
|
||||||
target?: string,
|
target?: string,
|
||||||
scopedVars?: ScopedVars,
|
scopedVars?: ScopedVars,
|
||||||
format?: string | Function | undefined,
|
format?: string | Function | undefined,
|
||||||
interpolations?: VariableInterpolation[]
|
interpolations?: VariableInterpolation[]
|
||||||
) => string
|
) => string = replaceMock
|
||||||
): TemplateSrv {
|
): TemplateSrv {
|
||||||
return {
|
return {
|
||||||
getAdhocFilters: getAdhocFiltersMock,
|
replace: rm,
|
||||||
replace: replaceMock,
|
|
||||||
} as unknown as TemplateSrv;
|
} as unknown as TemplateSrv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +33,7 @@ export function mockBackendService(response: FetchResponse) {
|
|||||||
|
|
||||||
export function getMockInfluxDS(
|
export function getMockInfluxDS(
|
||||||
instanceSettings: DataSourceInstanceSettings<InfluxOptions> = getMockDSInstanceSettings(),
|
instanceSettings: DataSourceInstanceSettings<InfluxOptions> = getMockDSInstanceSettings(),
|
||||||
templateSrv: TemplateSrv = templateSrvStub
|
templateSrv: TemplateSrv = mockTemplateSrv(replaceMock)
|
||||||
): InfluxDatasource {
|
): InfluxDatasource {
|
||||||
return new InfluxDatasource(instanceSettings, templateSrv);
|
return new InfluxDatasource(instanceSettings, templateSrv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export const mockInfluxQueryRequest = (targets?: QueryType[]): DataQueryRequest<
|
|||||||
from: dateTime(0),
|
from: dateTime(0),
|
||||||
to: dateTime(10),
|
to: dateTime(10),
|
||||||
},
|
},
|
||||||
|
filters: [{ key: 'adhoc_key', value: 'adhoc_val', operator: '=' }],
|
||||||
requestId: '',
|
requestId: '',
|
||||||
scopedVars: {},
|
scopedVars: {},
|
||||||
startTime: 0,
|
startTime: 0,
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import { lastValueFrom, of } from 'rxjs';
|
import { lastValueFrom, of } from 'rxjs';
|
||||||
|
|
||||||
import { BackendSrvRequest } from '@grafana/runtime';
|
import { BackendSrvRequest, TemplateSrv } from '@grafana/runtime';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
import { TemplateSrv } from '../../../features/templating/template_srv';
|
|
||||||
import { queryBuilder } from '../../../features/variables/shared/testing/builders';
|
import { queryBuilder } from '../../../features/variables/shared/testing/builders';
|
||||||
|
|
||||||
import { getMockDSInstanceSettings, getMockInfluxDS, mockBackendService } from './__mocks__/datasource';
|
import { getMockDSInstanceSettings, getMockInfluxDS, mockBackendService, replaceMock } from './__mocks__/datasource';
|
||||||
import { queryOptions } from './__mocks__/query';
|
import { mockInfluxQueryRequest } from './__mocks__/request';
|
||||||
import { mockInfluxQueryRequest, mockInfluxQueryWithTemplateVars } from './__mocks__/request';
|
|
||||||
import { mockInfluxFetchResponse, mockMetricFindQueryResponse } from './__mocks__/response';
|
import { mockInfluxFetchResponse, mockMetricFindQueryResponse } from './__mocks__/response';
|
||||||
import { BROWSER_MODE_DISABLED_MESSAGE } from './constants';
|
import { BROWSER_MODE_DISABLED_MESSAGE } from './constants';
|
||||||
import InfluxDatasource from './datasource';
|
import InfluxDatasource from './datasource';
|
||||||
import { InfluxQuery, InfluxVersion } from './types';
|
|
||||||
|
|
||||||
const fetchMock = mockBackendService(mockInfluxFetchResponse());
|
const fetchMock = mockBackendService(mockInfluxFetchResponse());
|
||||||
|
|
||||||
@@ -142,24 +139,11 @@ describe('InfluxDataSource Frontend Mode [influxdbBackendMigration=false]', () =
|
|||||||
|
|
||||||
// Update this after starting to use TemplateSrv from @grafana/runtime package
|
// Update this after starting to use TemplateSrv from @grafana/runtime package
|
||||||
describe('adhoc variables', () => {
|
describe('adhoc variables', () => {
|
||||||
const adhocFilters = [
|
let ds = getMockInfluxDS(getMockDSInstanceSettings());
|
||||||
{
|
|
||||||
key: 'adhoc_key',
|
|
||||||
operator: '=',
|
|
||||||
value: 'adhoc_val',
|
|
||||||
condition: '',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const mockTemplateService = new TemplateSrv();
|
|
||||||
mockTemplateService.getAdhocFilters = jest.fn((_: string) => adhocFilters);
|
|
||||||
let ds = getMockInfluxDS(getMockDSInstanceSettings(), mockTemplateService);
|
|
||||||
|
|
||||||
it('query should contain the ad-hoc variable', () => {
|
it('query should contain the ad-hoc variable', () => {
|
||||||
ds.query(mockInfluxQueryRequest());
|
ds.query(mockInfluxQueryRequest());
|
||||||
const expected = encodeURIComponent(
|
expect(replaceMock.mock.calls[0][0]).toBe('adhoc_val');
|
||||||
'SELECT mean("value") FROM "cpu" WHERE time >= 0ms and time <= 10ms AND "adhoc_key" = \'adhoc_val\' GROUP BY time($__interval) fill(null)'
|
|
||||||
);
|
|
||||||
expect(fetchMock.mock.calls[0][0].data).toBe(`q=${expected}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should make the fetch call for adhoc filter keys', () => {
|
it('should make the fetch call for adhoc filter keys', () => {
|
||||||
@@ -257,125 +241,6 @@ describe('InfluxDataSource Frontend Mode [influxdbBackendMigration=false]', () =
|
|||||||
expect(ds.database).toBe('fallback');
|
expect(ds.database).toBe('fallback');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('variable interpolation', () => {
|
|
||||||
const variablesMock = [
|
|
||||||
queryBuilder().withId('var1').withName('var1').withCurrent('var1_value').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],
|
|
||||||
getFilteredVariables: jest.fn(),
|
|
||||||
});
|
|
||||||
// Remove this after start using TemplateSrv from @grafana/runtime
|
|
||||||
mockTemplateService.getAdhocFilters = jest.fn();
|
|
||||||
|
|
||||||
describe('when interpolating query variables for dashboard->explore', () => {
|
|
||||||
it('should interpolate all variables with Flux mode', () => {
|
|
||||||
const ds = getMockInfluxDS(getMockDSInstanceSettings({ version: InfluxVersion.Flux }), mockTemplateService);
|
|
||||||
const fluxQuery = {
|
|
||||||
refId: 'x',
|
|
||||||
query: 'some query with $var1 and $path',
|
|
||||||
};
|
|
||||||
const queries = ds.interpolateVariablesInQueries([fluxQuery], {});
|
|
||||||
expect(queries[0].query).toBe('some query with var1_value and /etc/hosts');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should interpolate all variables with InfluxQL mode', () => {
|
|
||||||
const ds = getMockInfluxDS(getMockDSInstanceSettings({ version: InfluxVersion.InfluxQL }), mockTemplateService);
|
|
||||||
const [query] = ds.interpolateVariablesInQueries([mockInfluxQueryWithTemplateVars([])], {});
|
|
||||||
expect(query.alias).toBe('var1_value');
|
|
||||||
expect(query.measurement).toBe('var1_value');
|
|
||||||
expect(query.policy).toBe('var1_value');
|
|
||||||
expect(query.limit).toBe('var1_value');
|
|
||||||
expect(query.slimit).toBe('var1_value');
|
|
||||||
expect(query.tz).toBe('var1_value');
|
|
||||||
expect(query.tags![0].value).toBe(`/^\\/etc\\/hosts$/`);
|
|
||||||
expect(query.groupBy![0].params![0]).toBe('var1_value');
|
|
||||||
expect(query.select![0][0].params![0]).toBe('var1_value');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('applyTemplateVariables', () => {
|
|
||||||
it('should apply all template variables with Flux mode', () => {
|
|
||||||
const ds = getMockInfluxDS(getMockDSInstanceSettings({ version: InfluxVersion.Flux }), mockTemplateService);
|
|
||||||
const fluxQuery = {
|
|
||||||
refId: 'x',
|
|
||||||
query: '$var1',
|
|
||||||
};
|
|
||||||
const query = ds.applyTemplateVariables(fluxQuery, {});
|
|
||||||
expect(query.query).toBe('var1_value');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('variable interpolation with chained variables with frontend mode', () => {
|
|
||||||
let ds = getMockInfluxDS(getMockDSInstanceSettings(), mockTemplateService);
|
|
||||||
const fetchMockImpl = () =>
|
|
||||||
of({
|
|
||||||
data: {
|
|
||||||
status: 'success',
|
|
||||||
results: [
|
|
||||||
{
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'measurement',
|
|
||||||
columns: ['name'],
|
|
||||||
values: [['cpu']],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
fetchMock.mockImplementation(fetchMockImpl);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render chained regex variables with floating point number', () => {
|
|
||||||
ds.metricFindQuery(`SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= $maxSED`, {
|
|
||||||
scopedVars: { maxSED: { text: '8.1', value: '8.1' } },
|
|
||||||
});
|
|
||||||
const qe = `SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= 8.1`;
|
|
||||||
const qData = decodeURIComponent(fetchMock.mock.calls[0][0].data.substring(2));
|
|
||||||
expect(qData).toBe(qe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render chained regex variables with URL', () => {
|
|
||||||
ds.metricFindQuery('SHOW TAG VALUES WITH KEY = "agent_url" WHERE agent_url =~ /^$var1$/', {
|
|
||||||
scopedVars: {
|
|
||||||
var1: {
|
|
||||||
text: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
value: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const qe = `SHOW TAG VALUES WITH KEY = "agent_url" WHERE agent_url =~ /^https:\\/\\/aaaa-aa-aaa\\.bbb\\.ccc\\.ddd:8443\\/ggggg$/`;
|
|
||||||
const qData = decodeURIComponent(fetchMock.mock.calls[0][0].data.substring(2));
|
|
||||||
expect(qData).toBe(qe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render chained regex variables with floating point number and url', () => {
|
|
||||||
ds.metricFindQuery(
|
|
||||||
'SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= $maxSED AND agent_url =~ /^$var1$/',
|
|
||||||
{
|
|
||||||
scopedVars: {
|
|
||||||
var1: {
|
|
||||||
text: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
value: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
},
|
|
||||||
maxSED: { text: '8.1', value: '8.1' },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const qe = `SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= 8.1 AND agent_url =~ /^https:\\/\\/aaaa-aa-aaa\\.bbb\\.ccc\\.ddd:8443\\/ggggg$/`;
|
|
||||||
const qData = decodeURIComponent(fetchMock.mock.calls[0][0].data.substring(2));
|
|
||||||
expect(qData).toBe(qe);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('InfluxDataSource Backend Mode [influxdbBackendMigration=true]', () => {
|
describe('InfluxDataSource Backend Mode [influxdbBackendMigration=true]', () => {
|
||||||
@@ -399,171 +264,10 @@ describe('InfluxDataSource Backend Mode [influxdbBackendMigration=true]', () =>
|
|||||||
expect(values[0].text).toBe('test-t2-1');
|
expect(values[0].text).toBe('test-t2-1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('variable interpolation with chained variables with backend mode', () => {
|
|
||||||
const variablesMock = [
|
|
||||||
queryBuilder().withId('var1').withName('var1').withCurrent('var1').build(),
|
|
||||||
queryBuilder().withId('path').withName('path').withCurrent('/etc/hosts').build(),
|
|
||||||
queryBuilder()
|
|
||||||
.withId('field_var')
|
|
||||||
.withName('field_var')
|
|
||||||
.withMulti(true)
|
|
||||||
.withOptions(
|
|
||||||
{
|
|
||||||
text: `field_1`,
|
|
||||||
value: `field_1`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: `field_2`,
|
|
||||||
value: `field_2`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: `field_3`,
|
|
||||||
value: `field_3`,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.withCurrent(['field_1', 'field_3'])
|
|
||||||
.build(),
|
|
||||||
];
|
|
||||||
const mockTemplateService = new TemplateSrv({
|
|
||||||
getVariables: () => variablesMock,
|
|
||||||
getVariableWithName: (name: string) => variablesMock.filter((v) => v.name === name)[0],
|
|
||||||
getFilteredVariables: jest.fn(),
|
|
||||||
});
|
|
||||||
mockTemplateService.getAdhocFilters = jest.fn((_: string) => []);
|
|
||||||
let ds = getMockInfluxDS(getMockDSInstanceSettings(), mockTemplateService);
|
|
||||||
const fetchMockImpl = () =>
|
|
||||||
of({
|
|
||||||
data: {
|
|
||||||
status: 'success',
|
|
||||||
results: [
|
|
||||||
{
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'measurement',
|
|
||||||
columns: ['name'],
|
|
||||||
values: [['cpu']],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
fetchMock.mockImplementation(fetchMockImpl);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render chained regex variables with floating point number', () => {
|
|
||||||
ds.metricFindQuery(`SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= $maxSED`, {
|
|
||||||
...queryOptions,
|
|
||||||
scopedVars: { maxSED: { text: '8.1', value: '8.1' } },
|
|
||||||
});
|
|
||||||
const qe = `SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= 8.1`;
|
|
||||||
const qData = fetchMock.mock.calls[0][0].data.queries[0].query;
|
|
||||||
expect(qData).toBe(qe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render chained regex variables with URL', () => {
|
|
||||||
ds.metricFindQuery('SHOW TAG VALUES WITH KEY = "agent_url" WHERE agent_url =~ /^$var1$/', {
|
|
||||||
...queryOptions,
|
|
||||||
scopedVars: {
|
|
||||||
var1: {
|
|
||||||
text: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
value: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const qe = `SHOW TAG VALUES WITH KEY = "agent_url" WHERE agent_url =~ /^https:\\/\\/aaaa-aa-aaa\\.bbb\\.ccc\\.ddd:8443\\/ggggg$/`;
|
|
||||||
expect(fetchMock).toHaveBeenCalled();
|
|
||||||
const qData = fetchMock.mock.calls[0][0].data.queries[0].query;
|
|
||||||
expect(qData).toBe(qe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render chained regex variables with floating point number and url', () => {
|
|
||||||
ds.metricFindQuery(
|
|
||||||
'SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= $maxSED AND agent_url =~ /^$var1$/',
|
|
||||||
{
|
|
||||||
...queryOptions,
|
|
||||||
scopedVars: {
|
|
||||||
var1: {
|
|
||||||
text: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
value: 'https://aaaa-aa-aaa.bbb.ccc.ddd:8443/ggggg',
|
|
||||||
},
|
|
||||||
maxSED: { text: '8.1', value: '8.1' },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const qe = `SELECT sum("piece_count") FROM "rp"."pdata" WHERE diameter <= 8.1 AND agent_url =~ /^https:\\/\\/aaaa-aa-aaa\\.bbb\\.ccc\\.ddd:8443\\/ggggg$/`;
|
|
||||||
const qData = fetchMock.mock.calls[0][0].data.queries[0].query;
|
|
||||||
expect(qData).toBe(qe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should interpolate variable inside a regex pattern', () => {
|
|
||||||
const query: InfluxQuery = {
|
|
||||||
refId: 'A',
|
|
||||||
tags: [
|
|
||||||
{
|
|
||||||
key: 'key',
|
|
||||||
operator: '=~',
|
|
||||||
value: '/^.*-$var1$/',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const res = ds.applyVariables(query, {});
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should interpolate field keys with given scopedVars', () => {
|
|
||||||
const query: InfluxQuery = {
|
|
||||||
refId: 'A',
|
|
||||||
tags: [
|
|
||||||
{
|
|
||||||
key: 'key',
|
|
||||||
operator: '=',
|
|
||||||
value: 'value',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
select: [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
type: 'field',
|
|
||||||
params: ['$field_var'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'mean',
|
|
||||||
params: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const res = ds.applyVariables(query, { field_var: { text: 'field_3', value: 'field_3' } });
|
|
||||||
const expected = `field_3`;
|
|
||||||
expect(res.select?.[0][0].params?.[0]).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('interpolateQueryExpr', () => {
|
describe('interpolateQueryExpr', () => {
|
||||||
let ds = getMockInfluxDS(getMockDSInstanceSettings(), new TemplateSrv());
|
let ds = getMockInfluxDS(getMockDSInstanceSettings(), {} as TemplateSrv);
|
||||||
it('should return the value as it is', () => {
|
it('should return the value as it is', () => {
|
||||||
const value = 'normalValue';
|
const value = 'normalValue';
|
||||||
const variableMock = queryBuilder().withId('tempVar').withName('tempVar').withMulti(false).build();
|
const variableMock = queryBuilder().withId('tempVar').withName('tempVar').withMulti(false).build();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { lastValueFrom, merge, Observable, of, throwError } from 'rxjs';
|
|||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
AdHocVariableFilter,
|
||||||
AnnotationEvent,
|
AnnotationEvent,
|
||||||
DataFrame,
|
DataFrame,
|
||||||
DataQueryError,
|
DataQueryError,
|
||||||
@@ -31,10 +32,11 @@ import {
|
|||||||
FetchResponse,
|
FetchResponse,
|
||||||
frameToMetricFindValue,
|
frameToMetricFindValue,
|
||||||
getBackendSrv,
|
getBackendSrv,
|
||||||
|
getTemplateSrv,
|
||||||
|
TemplateSrv,
|
||||||
} from '@grafana/runtime';
|
} from '@grafana/runtime';
|
||||||
import { QueryFormat, SQLQuery } from '@grafana/sql';
|
import { QueryFormat, SQLQuery } from '@grafana/sql';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
|
|
||||||
|
|
||||||
import { AnnotationEditor } from './components/editor/annotation/AnnotationEditor';
|
import { AnnotationEditor } from './components/editor/annotation/AnnotationEditor';
|
||||||
import { FluxQueryEditor } from './components/editor/query/flux/FluxQueryEditor';
|
import { FluxQueryEditor } from './components/editor/query/flux/FluxQueryEditor';
|
||||||
@@ -170,7 +172,11 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyTemplateVariables(query: InfluxQuery, scopedVars: ScopedVars): InfluxQuery & SQLQuery {
|
applyTemplateVariables(
|
||||||
|
query: InfluxQuery,
|
||||||
|
scopedVars: ScopedVars,
|
||||||
|
filters?: AdHocVariableFilter[]
|
||||||
|
): InfluxQuery & SQLQuery {
|
||||||
const variables = scopedVars || {};
|
const variables = scopedVars || {};
|
||||||
|
|
||||||
// We want to interpolate these variables on backend.
|
// We want to interpolate these variables on backend.
|
||||||
@@ -190,7 +196,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.version === InfluxVersion.SQL || this.isMigrationToggleOnAndIsAccessProxy()) {
|
if (this.version === InfluxVersion.SQL || this.isMigrationToggleOnAndIsAccessProxy()) {
|
||||||
query = this.applyVariables(query, variables);
|
query = this.applyVariables(query, variables, filters);
|
||||||
if (query.adhocFilters?.length) {
|
if (query.adhocFilters?.length) {
|
||||||
const adhocFiltersToTags: InfluxQueryTag[] = (query.adhocFilters ?? []).map((af) => {
|
const adhocFiltersToTags: InfluxQueryTag[] = (query.adhocFilters ?? []).map((af) => {
|
||||||
const { condition, ...asTag } = af;
|
const { condition, ...asTag } = af;
|
||||||
@@ -238,7 +244,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
applyVariables(query: InfluxQuery & SQLQuery, scopedVars: ScopedVars) {
|
applyVariables(query: InfluxQuery & SQLQuery, scopedVars: ScopedVars, filters?: AdHocVariableFilter[]) {
|
||||||
const expandedQuery = { ...query };
|
const expandedQuery = { ...query };
|
||||||
if (query.groupBy) {
|
if (query.groupBy) {
|
||||||
expandedQuery.groupBy = query.groupBy.map((groupBy) => {
|
expandedQuery.groupBy = query.groupBy.map((groupBy) => {
|
||||||
@@ -282,7 +288,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...expandedQuery,
|
...expandedQuery,
|
||||||
adhocFilters: this.templateSrv.getAdhocFilters(this.name) ?? [],
|
adhocFilters: filters ?? [],
|
||||||
query: this.templateSrv.replace(
|
query: this.templateSrv.replace(
|
||||||
query.query ?? '',
|
query.query ?? '',
|
||||||
scopedVars,
|
scopedVars,
|
||||||
@@ -651,7 +657,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add global adhoc filters to timeFilter
|
// add global adhoc filters to timeFilter
|
||||||
const adhocFilters = this.templateSrv.getAdhocFilters(this.name);
|
const adhocFilters = options.filters;
|
||||||
const adhocFiltersFromDashboard = options.targets.flatMap((target: InfluxQuery) => target.adhocFilters ?? []);
|
const adhocFiltersFromDashboard = options.targets.flatMap((target: InfluxQuery) => target.adhocFilters ?? []);
|
||||||
if (adhocFilters?.length || adhocFiltersFromDashboard?.length) {
|
if (adhocFilters?.length || adhocFiltersFromDashboard?.length) {
|
||||||
const ahFilters = adhocFilters?.length ? adhocFilters : adhocFiltersFromDashboard;
|
const ahFilters = adhocFilters?.length ? adhocFilters : adhocFiltersFromDashboard;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ mockBackendService(mockInfluxSQLFetchResponse);
|
|||||||
|
|
||||||
describe('InfluxDB SQL Support', () => {
|
describe('InfluxDB SQL Support', () => {
|
||||||
const replaceMock = jest.fn();
|
const replaceMock = jest.fn();
|
||||||
const templateSrv = mockTemplateSrv(jest.fn(), replaceMock);
|
const templateSrv = mockTemplateSrv(replaceMock);
|
||||||
|
|
||||||
let sqlQuery: SQLQuery;
|
let sqlQuery: SQLQuery;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
import { TemplateSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import InfluxQueryModel from './influx_query_model';
|
import InfluxQueryModel from './influx_query_model';
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { reduce } from 'lodash';
|
import { reduce } from 'lodash';
|
||||||
|
|
||||||
import { escapeRegex, ScopedVars } from '@grafana/data/src';
|
import { escapeRegex, ScopedVars } from '@grafana/data';
|
||||||
|
import { TemplateSrv } from '@grafana/runtime';
|
||||||
import { TemplateSrv } from '../../../features/templating/template_srv';
|
|
||||||
|
|
||||||
import { DEFAULT_POLICY, InfluxQueryTag, MetadataQueryType } from './types';
|
import { DEFAULT_POLICY, InfluxQueryTag, MetadataQueryType } from './types';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user