AzureMonitor: Ensure original query properties are included unchanged (#49642)

* Ensure original query properties are included unchanged

* Remove refId from pseudo datasources

* Include testing for interpolateVariablesInQueries

- Add util function to create template variables
- Update mock query with missing props
- Additional tests on each ds for template variables

* Correct typo and add explicit check for datasource
This commit is contained in:
Andreas Christou 2022-05-26 14:53:12 +01:00 committed by GitHub
parent 1308e28d8b
commit c8094b33cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 176 additions and 8 deletions

View File

@ -7,10 +7,12 @@ export default function createMockQuery(): AzureMonitorQuery {
'//change this example to create your own time series query\n<table name> //the table to query (e.g. Usage, Heartbeat, Perf)\n| where $__timeFilter(TimeGenerated) //this is a macro used to show the full charts time range, choose the datetime column here\n| summarize count() by <group by column>, bin(TimeGenerated, $__interval) //change “group by column” to a column in your table, such as “Computer”. The $__interval macro is used to auto-select the time grain. Can also use 1h, 5m etc.\n| order by TimeGenerated asc',
resultFormat: 'time_series',
workspace: 'e3fe4fde-ad5e-4d60-9974-e2f3562ffdf2',
resource: 'test-resource',
},
azureResourceGraph: {
query: 'Resources | summarize count()',
resultFormat: 'table',
},
azureMonitor: {
@ -36,5 +38,9 @@ export default function createMockQuery(): AzureMonitorQuery {
refId: 'A',
subscription: '99999999-cccc-bbbb-aaaa-9106972f9572',
subscriptions: ['99999999-cccc-bbbb-aaaa-9106972f9572'],
datasource: {
type: 'grafana-azure-monitor-datasource',
uid: 'AAAAA11111BBBBB22222CCCC',
},
};
}

View File

@ -0,0 +1,40 @@
import { VariableType } from '@grafana/data';
import { LoadingState } from '@grafana/data/src/types/data';
import { VariableWithOptions } from 'app/features/variables/types';
interface TemplateableValue {
variableName: string;
templateVariable: VariableWithOptions;
}
export function createTemplateVariables(templateableProps: string[]): Map<string, TemplateableValue> {
const templateVariables = new Map<string, TemplateableValue>();
templateableProps.map((prop) => {
const variableName = prop.replace(/[\[\].]/g, '');
const templateVariable = {
current: {
selected: false,
text: `${variableName}-template-variable`,
value: `${variableName}-template-variable`,
},
id: variableName,
name: variableName,
type: 'textbox' as VariableType,
options: [],
query: '',
rootStateKey: null,
global: false,
hide: 0,
skipUrlSync: false,
index: 0,
state: 'Done' as LoadingState,
error: null,
description: null,
};
templateVariables.set(prop, {
variableName,
templateVariable,
});
});
return templateVariables;
}

View File

@ -1,7 +1,10 @@
import { get, set } from 'lodash';
import { toUtc } from '@grafana/data';
import { TemplateSrv } from 'app/features/templating/template_srv';
import createMockQuery from '../__mocks__/query';
import { createTemplateVariables } from '../__mocks__/utils';
import { singleVariable } from '../__mocks__/variables';
import AzureMonitorDatasource from '../datasource';
import { AzureMonitorQuery, AzureQueryType, DatasourceValidationResult } from '../types';
@ -369,4 +372,38 @@ describe('AzureLogAnalyticsDatasource', () => {
expect(laDatasource.filterQuery(query)).toBeFalsy();
});
});
describe('When performing interpolateVariablesInQueries for azure_log_analytics', () => {
beforeEach(() => {
templateSrv.init([]);
});
it('should return a query unchanged if no template variables are provided', () => {
const query = createMockQuery();
query.queryType = AzureQueryType.LogAnalytics;
const templatedQuery = ctx.ds.interpolateVariablesInQueries([query], {});
expect(templatedQuery[0]).toEqual(query);
});
it('should return a query with any template variables replaced', () => {
const templateableProps = ['resource', 'workspace', 'query'];
const templateVariables = createTemplateVariables(templateableProps);
templateSrv.init(Array.from(templateVariables.values()).map((item) => item.templateVariable));
const query = createMockQuery();
const azureLogAnalytics: { [index: string]: any } = {};
for (const [path, templateVariable] of templateVariables.entries()) {
set(azureLogAnalytics, path, `$${templateVariable.variableName}`);
}
query.queryType = AzureQueryType.LogAnalytics;
query.azureLogAnalytics = {
...query.azureLogAnalytics,
...azureLogAnalytics,
};
const templatedQuery = ctx.ds.interpolateVariablesInQueries([query], {});
expect(templatedQuery[0]).toHaveProperty('datasource');
for (const [path, templateVariable] of templateVariables.entries()) {
expect(get(templatedQuery[0].azureLogAnalytics, path)).toEqual(templateVariable.templateVariable.current.value);
}
});
});
});

View File

@ -134,7 +134,7 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
const query = templateSrv.replace(item.query, scopedVars, interpolateVariable);
return {
refId: target.refId,
...target,
queryType: AzureQueryType.LogAnalytics,
azureLogAnalytics: {

View File

@ -1,9 +1,10 @@
import { startsWith } from 'lodash';
import { startsWith, get, set } from 'lodash';
import { DataSourceInstanceSettings } from '@grafana/data';
import { TemplateSrv } from 'app/features/templating/template_srv';
import createMockQuery from '../__mocks__/query';
import { createTemplateVariables } from '../__mocks__/utils';
import { singleVariable, subscriptionsVariable } from '../__mocks__/variables';
import AzureMonitorDatasource from '../datasource';
import { AzureDataSourceJsonData, AzureQueryType, DatasourceValidationResult } from '../types';
@ -259,6 +260,50 @@ describe('AzureMonitorDatasource', () => {
});
});
describe('When performing interpolateVariablesInQueries for azure_monitor_metrics', () => {
beforeEach(() => {
templateSrv.init([]);
});
it('should return a query unchanged if no template variables are provided', () => {
const query = createMockQuery();
const templatedQuery = ctx.ds.interpolateVariablesInQueries([query], {});
expect(templatedQuery[0]).toEqual(query);
});
it('should return a query with any template variables replaced', () => {
const templateableProps = [
'resourceUri',
'resourceGroup',
'resourceName',
'metricNamespace',
'metricDefinition',
'timeGrain',
'aggregation',
'top',
'dimensionFilters[0].dimension',
'dimensionFilters[0].filters[0]',
];
const templateVariables = createTemplateVariables(templateableProps);
templateSrv.init(Array.from(templateVariables.values()).map((item) => item.templateVariable));
const query = createMockQuery();
const azureMonitorQuery: { [index: string]: any } = {};
for (const [path, templateVariable] of templateVariables.entries()) {
set(azureMonitorQuery, path, `$${templateVariable.variableName}`);
}
query.azureMonitor = {
...query.azureMonitor,
...azureMonitorQuery,
};
const templatedQuery = ctx.ds.interpolateVariablesInQueries([query], {});
expect(templatedQuery[0]).toHaveProperty('datasource');
for (const [path, templateVariable] of templateVariables.entries()) {
expect(get(templatedQuery[0].azureMonitor, path)).toEqual(templateVariable.templateVariable.current.value);
}
});
});
describe('Legacy Azure Monitor Query Object data fetchers', () => {
describe('When performing getSubscriptions', () => {
const response = {

View File

@ -114,7 +114,7 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
});
return {
refId: target.refId,
...target,
subscription: subscriptionId,
queryType: AzureQueryType.AzureMonitor,
azureMonitor: {

View File

@ -1,7 +1,10 @@
import { set, get } from 'lodash';
import { backendSrv } from 'app/core/services/backend_srv';
import { TemplateSrv } from 'app/features/templating/template_srv';
import createMockQuery from '../__mocks__/query';
import { createTemplateVariables } from '../__mocks__/utils';
import { multiVariable, singleVariable, subscriptionsVariable } from '../__mocks__/variables';
import AzureMonitorDatasource from '../datasource';
import { AzureQueryType } from '../types';
@ -13,7 +16,6 @@ const templateSrv = new TemplateSrv({
getVariableWithName: jest.fn(),
getFilteredVariables: jest.fn(),
});
templateSrv.init([subscriptionsVariable, singleVariable, multiVariable]);
jest.mock('app/core/services/backend_srv');
jest.mock('@grafana/runtime', () => ({
@ -41,7 +43,48 @@ describe('AzureResourceGraphDatasource', () => {
ctx.ds = new AzureResourceGraphDatasource(ctx.instanceSettings);
});
describe('When performing interpolateVariablesInQueries for azure_resource_graph', () => {
beforeEach(() => {
templateSrv.init([]);
});
it('should return a query unchanged if no template variables are provided', () => {
const query = createMockQuery();
query.queryType = AzureQueryType.AzureResourceGraph;
const templatedQuery = ctx.ds.interpolateVariablesInQueries([query], {});
expect(templatedQuery[0]).toEqual(query);
});
it('should return a query with any template variables replaced', () => {
const templateableProps = ['query'];
const templateVariables = createTemplateVariables(templateableProps);
templateSrv.init(Array.from(templateVariables.values()).map((item) => item.templateVariable));
const query = createMockQuery();
const azureResourceGraph: { [index: string]: any } = {};
for (const [path, templateVariable] of templateVariables.entries()) {
set(azureResourceGraph, path, `$${templateVariable.variableName}`);
}
query.queryType = AzureQueryType.AzureResourceGraph;
query.azureResourceGraph = {
...query.azureResourceGraph,
...azureResourceGraph,
};
const templatedQuery = ctx.ds.interpolateVariablesInQueries([query], {});
expect(templatedQuery[0]).toHaveProperty('datasource');
for (const [path, templateVariable] of templateVariables.entries()) {
expect(get(templatedQuery[0].azureResourceGraph, path)).toEqual(
templateVariable.templateVariable.current.value
);
}
});
});
describe('When applying template variables', () => {
beforeEach(() => {
templateSrv.init([subscriptionsVariable, singleVariable, multiVariable]);
});
it('should expand single value template variable', () => {
const target = {
azureResourceGraph: {
@ -52,7 +95,6 @@ describe('AzureResourceGraphDatasource', () => {
expect(ctx.ds.applyTemplateVariables(target)).toStrictEqual({
azureResourceGraph: { query: 'Resources | var1-foo', resultFormat: 'table' },
queryType: 'Azure Resource Graph',
refId: undefined,
subscriptions: [],
});
});
@ -70,7 +112,6 @@ describe('AzureResourceGraphDatasource', () => {
resultFormat: 'table',
},
queryType: 'Azure Resource Graph',
refId: undefined,
subscriptions: [],
});
});
@ -90,7 +131,6 @@ describe('AzureResourceGraphDatasource', () => {
resultFormat: 'table',
},
queryType: 'Azure Resource Graph',
refId: undefined,
subscriptions: ['sub-foo', 'sub-baz'],
});
});

View File

@ -35,7 +35,7 @@ export default class AzureResourceGraphDatasource extends DataSourceWithBackend<
const query = templateSrv.replace(item.query, scopedVars, interpolateVariable);
return {
refId: target.refId,
...target,
queryType: AzureQueryType.AzureResourceGraph,
subscriptions,
azureResourceGraph: {