mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 01:23:32 -06:00
Chore: Use TemplateSrv from @grafana/runtime in influxdb datasource (#87813)
use templatesrv from @grafana/runtime
This commit is contained in:
parent
699c5bfe79
commit
4fef6ff30d
@ -1,32 +1,23 @@
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { AdHocVariableFilter, DataSourceInstanceSettings, PluginType, ScopedVars } from '@grafana/data';
|
||||
import { FetchResponse, getBackendSrv, setBackendSrv, VariableInterpolation } from '@grafana/runtime';
|
||||
import { DataSourceInstanceSettings, PluginType, ScopedVars } from '@grafana/data';
|
||||
import { FetchResponse, getBackendSrv, setBackendSrv, TemplateSrv, VariableInterpolation } from '@grafana/runtime';
|
||||
|
||||
import { TemplateSrv } from '../../../../features/templating/template_srv';
|
||||
import InfluxDatasource from '../datasource';
|
||||
import { InfluxOptions, InfluxVersion } from '../types';
|
||||
|
||||
const getAdhocFiltersMock = jest.fn().mockImplementation(() => []);
|
||||
const replaceMock = jest.fn().mockImplementation((a: string, ...rest: unknown[]) => a);
|
||||
|
||||
export const templateSrvStub = {
|
||||
getAdhocFilters: getAdhocFiltersMock,
|
||||
replace: replaceMock,
|
||||
} as unknown as TemplateSrv;
|
||||
|
||||
export const replaceMock = jest.fn().mockImplementation((a: string, ...rest: unknown[]) => a);
|
||||
export const templateSrvStub = mockTemplateSrv(replaceMock);
|
||||
export function mockTemplateSrv(
|
||||
getAdhocFiltersMock: (datasourceName: string) => AdHocVariableFilter[],
|
||||
replaceMock: (
|
||||
rm: (
|
||||
target?: string,
|
||||
scopedVars?: ScopedVars,
|
||||
format?: string | Function | undefined,
|
||||
interpolations?: VariableInterpolation[]
|
||||
) => string
|
||||
) => string = replaceMock
|
||||
): TemplateSrv {
|
||||
return {
|
||||
getAdhocFilters: getAdhocFiltersMock,
|
||||
replace: replaceMock,
|
||||
replace: rm,
|
||||
} as unknown as TemplateSrv;
|
||||
}
|
||||
|
||||
@ -42,7 +33,7 @@ export function mockBackendService(response: FetchResponse) {
|
||||
|
||||
export function getMockInfluxDS(
|
||||
instanceSettings: DataSourceInstanceSettings<InfluxOptions> = getMockDSInstanceSettings(),
|
||||
templateSrv: TemplateSrv = templateSrvStub
|
||||
templateSrv: TemplateSrv = mockTemplateSrv(replaceMock)
|
||||
): InfluxDatasource {
|
||||
return new InfluxDatasource(instanceSettings, templateSrv);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ export const mockInfluxQueryRequest = (targets?: QueryType[]): DataQueryRequest<
|
||||
from: dateTime(0),
|
||||
to: dateTime(10),
|
||||
},
|
||||
filters: [{ key: 'adhoc_key', value: 'adhoc_val', operator: '=' }],
|
||||
requestId: '',
|
||||
scopedVars: {},
|
||||
startTime: 0,
|
||||
|
@ -1,18 +1,15 @@
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
|
||||
import { BackendSrvRequest } from '@grafana/runtime';
|
||||
import { BackendSrvRequest, TemplateSrv } from '@grafana/runtime';
|
||||
import config from 'app/core/config';
|
||||
|
||||
import { TemplateSrv } from '../../../features/templating/template_srv';
|
||||
import { queryBuilder } from '../../../features/variables/shared/testing/builders';
|
||||
|
||||
import { getMockDSInstanceSettings, getMockInfluxDS, mockBackendService } from './__mocks__/datasource';
|
||||
import { queryOptions } from './__mocks__/query';
|
||||
import { mockInfluxQueryRequest, mockInfluxQueryWithTemplateVars } from './__mocks__/request';
|
||||
import { getMockDSInstanceSettings, getMockInfluxDS, mockBackendService, replaceMock } from './__mocks__/datasource';
|
||||
import { mockInfluxQueryRequest } from './__mocks__/request';
|
||||
import { mockInfluxFetchResponse, mockMetricFindQueryResponse } from './__mocks__/response';
|
||||
import { BROWSER_MODE_DISABLED_MESSAGE } from './constants';
|
||||
import InfluxDatasource from './datasource';
|
||||
import { InfluxQuery, InfluxVersion } from './types';
|
||||
|
||||
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
|
||||
describe('adhoc variables', () => {
|
||||
const adhocFilters = [
|
||||
{
|
||||
key: 'adhoc_key',
|
||||
operator: '=',
|
||||
value: 'adhoc_val',
|
||||
condition: '',
|
||||
},
|
||||
];
|
||||
const mockTemplateService = new TemplateSrv();
|
||||
mockTemplateService.getAdhocFilters = jest.fn((_: string) => adhocFilters);
|
||||
let ds = getMockInfluxDS(getMockDSInstanceSettings(), mockTemplateService);
|
||||
let ds = getMockInfluxDS(getMockDSInstanceSettings());
|
||||
|
||||
it('query should contain the ad-hoc variable', () => {
|
||||
ds.query(mockInfluxQueryRequest());
|
||||
const expected = encodeURIComponent(
|
||||
'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}`);
|
||||
expect(replaceMock.mock.calls[0][0]).toBe('adhoc_val');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
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]', () => {
|
||||
@ -399,171 +264,10 @@ describe('InfluxDataSource Backend Mode [influxdbBackendMigration=true]', () =>
|
||||
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', () => {
|
||||
let ds = getMockInfluxDS(getMockDSInstanceSettings(), new TemplateSrv());
|
||||
let ds = getMockInfluxDS(getMockDSInstanceSettings(), {} as TemplateSrv);
|
||||
it('should return the value as it is', () => {
|
||||
const value = 'normalValue';
|
||||
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 {
|
||||
AdHocVariableFilter,
|
||||
AnnotationEvent,
|
||||
DataFrame,
|
||||
DataQueryError,
|
||||
@ -31,10 +32,11 @@ import {
|
||||
FetchResponse,
|
||||
frameToMetricFindValue,
|
||||
getBackendSrv,
|
||||
getTemplateSrv,
|
||||
TemplateSrv,
|
||||
} from '@grafana/runtime';
|
||||
import { QueryFormat, SQLQuery } from '@grafana/sql';
|
||||
import config from 'app/core/config';
|
||||
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
|
||||
|
||||
import { AnnotationEditor } from './components/editor/annotation/AnnotationEditor';
|
||||
import { FluxQueryEditor } from './components/editor/query/flux/FluxQueryEditor';
|
||||
@ -170,7 +172,11 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
||||
return true;
|
||||
}
|
||||
|
||||
applyTemplateVariables(query: InfluxQuery, scopedVars: ScopedVars): InfluxQuery & SQLQuery {
|
||||
applyTemplateVariables(
|
||||
query: InfluxQuery,
|
||||
scopedVars: ScopedVars,
|
||||
filters?: AdHocVariableFilter[]
|
||||
): InfluxQuery & SQLQuery {
|
||||
const variables = scopedVars || {};
|
||||
|
||||
// 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()) {
|
||||
query = this.applyVariables(query, variables);
|
||||
query = this.applyVariables(query, variables, filters);
|
||||
if (query.adhocFilters?.length) {
|
||||
const adhocFiltersToTags: InfluxQueryTag[] = (query.adhocFilters ?? []).map((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 };
|
||||
if (query.groupBy) {
|
||||
expandedQuery.groupBy = query.groupBy.map((groupBy) => {
|
||||
@ -282,7 +288,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
||||
|
||||
return {
|
||||
...expandedQuery,
|
||||
adhocFilters: this.templateSrv.getAdhocFilters(this.name) ?? [],
|
||||
adhocFilters: filters ?? [],
|
||||
query: this.templateSrv.replace(
|
||||
query.query ?? '',
|
||||
scopedVars,
|
||||
@ -651,7 +657,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
||||
}
|
||||
|
||||
// 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 ?? []);
|
||||
if (adhocFilters?.length || adhocFiltersFromDashboard?.length) {
|
||||
const ahFilters = adhocFilters?.length ? adhocFilters : adhocFiltersFromDashboard;
|
||||
|
@ -14,7 +14,7 @@ mockBackendService(mockInfluxSQLFetchResponse);
|
||||
|
||||
describe('InfluxDB SQL Support', () => {
|
||||
const replaceMock = jest.fn();
|
||||
const templateSrv = mockTemplateSrv(jest.fn(), replaceMock);
|
||||
const templateSrv = mockTemplateSrv(replaceMock);
|
||||
|
||||
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';
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { reduce } from 'lodash';
|
||||
|
||||
import { escapeRegex, ScopedVars } from '@grafana/data/src';
|
||||
|
||||
import { TemplateSrv } from '../../../features/templating/template_srv';
|
||||
import { escapeRegex, ScopedVars } from '@grafana/data';
|
||||
import { TemplateSrv } from '@grafana/runtime';
|
||||
|
||||
import { DEFAULT_POLICY, InfluxQueryTag, MetadataQueryType } from './types';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user