mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Azure monitor: Make sure alert rule editor is not enabled when template variables are being used (#41335)
* check if variable exist in query * add tests * pr feedback
This commit is contained in:
parent
cbc00babe4
commit
07754351b7
@ -0,0 +1,51 @@
|
||||
import { CustomVariableModel, initialVariableModelState, VariableHide } from 'app/features/variables/types';
|
||||
|
||||
export const subscriptionsVariable: CustomVariableModel = {
|
||||
...initialVariableModelState,
|
||||
id: 'subs',
|
||||
name: 'subs',
|
||||
index: 3,
|
||||
current: { value: ['sub-foo', 'sub-baz'], text: 'sub-foo + sub-baz', selected: true },
|
||||
options: [
|
||||
{ selected: true, value: 'sub-foo', text: 'sub-foo' },
|
||||
{ selected: false, value: 'sub-bar', text: 'sub-bar' },
|
||||
{ selected: true, value: 'sub-baz', text: 'sub-baz' },
|
||||
],
|
||||
multi: true,
|
||||
includeAll: false,
|
||||
query: '',
|
||||
hide: VariableHide.dontHide,
|
||||
type: 'custom',
|
||||
};
|
||||
|
||||
export const singleVariable: CustomVariableModel = {
|
||||
...initialVariableModelState,
|
||||
id: 'var1',
|
||||
name: 'var1',
|
||||
index: 0,
|
||||
current: { value: 'var1-foo', text: 'var1-foo', selected: true },
|
||||
options: [{ value: 'var1-foo', text: 'var1-foo', selected: true }],
|
||||
multi: false,
|
||||
includeAll: false,
|
||||
query: '',
|
||||
hide: VariableHide.dontHide,
|
||||
type: 'custom',
|
||||
};
|
||||
|
||||
export const multiVariable: CustomVariableModel = {
|
||||
...initialVariableModelState,
|
||||
id: 'var3',
|
||||
name: 'var3',
|
||||
index: 2,
|
||||
current: { value: ['var3-foo', 'var3-baz'], text: 'var3-foo + var3-baz', selected: true },
|
||||
options: [
|
||||
{ selected: true, value: 'var3-foo', text: 'var3-foo' },
|
||||
{ selected: false, value: 'var3-bar', text: 'var3-bar' },
|
||||
{ selected: true, value: 'var3-baz', text: 'var3-baz' },
|
||||
],
|
||||
multi: true,
|
||||
includeAll: false,
|
||||
query: '',
|
||||
hide: VariableHide.dontHide,
|
||||
type: 'custom',
|
||||
};
|
@ -2,8 +2,10 @@ import AzureMonitorDatasource from '../datasource';
|
||||
import AzureLogAnalyticsDatasource from './azure_log_analytics_datasource';
|
||||
import FakeSchemaData from './__mocks__/schema';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { AzureMonitorQuery, DatasourceValidationResult } from '../types';
|
||||
import { AzureMonitorQuery, AzureQueryType, DatasourceValidationResult } from '../types';
|
||||
import { toUtc } from '@grafana/data';
|
||||
import createMockQuery from '../__mocks__/query';
|
||||
import { singleVariable } from '../__mocks__/variables';
|
||||
|
||||
const templateSrv = new TemplateSrv();
|
||||
|
||||
@ -227,6 +229,37 @@ describe('AzureLogAnalyticsDatasource', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('When performing targetContainsTemplate', () => {
|
||||
it('should return false when no variable is being used', () => {
|
||||
const query = createMockQuery();
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings);
|
||||
query.queryType = AzureQueryType.LogAnalytics;
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return true when resource field is using a variable', () => {
|
||||
const templateSrv = new TemplateSrv();
|
||||
const query = createMockQuery();
|
||||
templateSrv.init([singleVariable]);
|
||||
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.LogAnalytics;
|
||||
query.azureLogAnalytics = { resource: `$${singleVariable.name}` };
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return false when a variable is used in a different part of the query', () => {
|
||||
const templateSrv = new TemplateSrv();
|
||||
const query = createMockQuery();
|
||||
templateSrv.init([singleVariable]);
|
||||
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.LogAnalytics;
|
||||
query.azureResourceGraph = { query: `$${singleVariable.name}` };
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When performing filterQuery', () => {
|
||||
const ctx: any = {};
|
||||
let laDatasource: AzureLogAnalyticsDatasource;
|
||||
|
@ -2,7 +2,9 @@ import AzureMonitorDatasource from '../datasource';
|
||||
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { DataSourceInstanceSettings } from '@grafana/data';
|
||||
import { AzureDataSourceJsonData, DatasourceValidationResult } from '../types';
|
||||
import { AzureDataSourceJsonData, AzureQueryType, DatasourceValidationResult } from '../types';
|
||||
import createMockQuery from '../__mocks__/query';
|
||||
import { singleVariable, subscriptionsVariable } from '../__mocks__/variables';
|
||||
|
||||
const templateSrv = new TemplateSrv();
|
||||
|
||||
@ -485,6 +487,36 @@ describe('AzureMonitorDatasource', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('When performing targetContainsTemplate', () => {
|
||||
it('should return false when no variable is being used', () => {
|
||||
const query = createMockQuery();
|
||||
query.queryType = AzureQueryType.AzureMonitor;
|
||||
expect(ctx.ds.targetContainsTemplate(query)).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return true when subscriptions field is using a variable', () => {
|
||||
const query = createMockQuery();
|
||||
const templateSrv = new TemplateSrv();
|
||||
templateSrv.init([subscriptionsVariable]);
|
||||
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.AzureMonitor;
|
||||
query.subscription = `$${subscriptionsVariable.name}`;
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return false when a variable is used in a different part of the query', () => {
|
||||
const query = createMockQuery();
|
||||
const templateSrv = new TemplateSrv();
|
||||
templateSrv.init([singleVariable]);
|
||||
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.AzureMonitor;
|
||||
query.azureLogAnalytics = { resource: `$${singleVariable.name}` };
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty array for a Metric that does not have dimensions', () => {
|
||||
return ctx.ds
|
||||
.getMetricMetadata(
|
||||
|
@ -1,64 +1,17 @@
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
import AzureResourceGraphDatasource from './azure_resource_graph_datasource';
|
||||
import { CustomVariableModel, initialVariableModelState, VariableHide } from 'app/features/variables/types';
|
||||
|
||||
const single: CustomVariableModel = {
|
||||
...initialVariableModelState,
|
||||
id: 'var1',
|
||||
name: 'var1',
|
||||
index: 0,
|
||||
current: { value: 'var1-foo', text: 'var1-foo', selected: true },
|
||||
options: [{ value: 'var1-foo', text: 'var1-foo', selected: true }],
|
||||
multi: false,
|
||||
includeAll: false,
|
||||
query: '',
|
||||
hide: VariableHide.dontHide,
|
||||
type: 'custom',
|
||||
};
|
||||
|
||||
const multi: CustomVariableModel = {
|
||||
...initialVariableModelState,
|
||||
id: 'var3',
|
||||
name: 'var3',
|
||||
index: 2,
|
||||
current: { value: ['var3-foo', 'var3-baz'], text: 'var3-foo + var3-baz', selected: true },
|
||||
options: [
|
||||
{ selected: true, value: 'var3-foo', text: 'var3-foo' },
|
||||
{ selected: false, value: 'var3-bar', text: 'var3-bar' },
|
||||
{ selected: true, value: 'var3-baz', text: 'var3-baz' },
|
||||
],
|
||||
multi: true,
|
||||
includeAll: false,
|
||||
query: '',
|
||||
hide: VariableHide.dontHide,
|
||||
type: 'custom',
|
||||
};
|
||||
|
||||
const subs: CustomVariableModel = {
|
||||
...initialVariableModelState,
|
||||
id: 'subs',
|
||||
name: 'subs',
|
||||
index: 3,
|
||||
current: { value: ['sub-foo', 'sub-baz'], text: 'sub-foo + sub-baz', selected: true },
|
||||
options: [
|
||||
{ selected: true, value: 'sub-foo', text: 'sub-foo' },
|
||||
{ selected: false, value: 'sub-bar', text: 'sub-bar' },
|
||||
{ selected: true, value: 'sub-baz', text: 'sub-baz' },
|
||||
],
|
||||
multi: true,
|
||||
includeAll: false,
|
||||
query: '',
|
||||
hide: VariableHide.dontHide,
|
||||
type: 'custom',
|
||||
};
|
||||
import { multiVariable, singleVariable, subscriptionsVariable } from '../__mocks__/variables';
|
||||
import { AzureQueryType } from '../types';
|
||||
import AzureMonitorDatasource from '../datasource';
|
||||
import createMockQuery from '../__mocks__/query';
|
||||
|
||||
const templateSrv = new TemplateSrv({
|
||||
getVariables: () => [subs, single, multi],
|
||||
getVariables: () => [subscriptionsVariable, singleVariable, multiVariable],
|
||||
getVariableWithName: jest.fn(),
|
||||
getFilteredVariables: jest.fn(),
|
||||
});
|
||||
templateSrv.init([subs, single, multi]);
|
||||
templateSrv.init([subscriptionsVariable, singleVariable, multiVariable]);
|
||||
|
||||
jest.mock('app/core/services/backend_srv');
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
@ -80,6 +33,7 @@ describe('AzureResourceGraphDatasource', () => {
|
||||
beforeEach(() => {
|
||||
ctx.instanceSettings = {
|
||||
url: 'http://azureresourcegraphapi',
|
||||
jsonData: { subscriptionId: '9935389e-9122-4ef9-95f9-1513dd24753f', cloudName: 'azuremonitor' },
|
||||
};
|
||||
|
||||
ctx.ds = new AzureResourceGraphDatasource(ctx.instanceSettings);
|
||||
@ -138,4 +92,47 @@ describe('AzureResourceGraphDatasource', () => {
|
||||
subscriptions: ['sub-foo', 'sub-baz'],
|
||||
});
|
||||
});
|
||||
|
||||
describe('When performing targetContainsTemplate', () => {
|
||||
it('should return false when no variable is being used', () => {
|
||||
const query = createMockQuery();
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.AzureResourceGraph;
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return true when resource field is using a variable', () => {
|
||||
const query = createMockQuery();
|
||||
const templateSrv = new TemplateSrv();
|
||||
templateSrv.init([singleVariable]);
|
||||
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.AzureResourceGraph;
|
||||
query.azureResourceGraph = { query: `$${singleVariable.name}` };
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return true when resource field is using a variable in the subscriptions field', () => {
|
||||
const query = createMockQuery();
|
||||
const templateSrv = new TemplateSrv();
|
||||
templateSrv.init([multiVariable]);
|
||||
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.AzureResourceGraph;
|
||||
query.subscriptions = [multiVariable.name];
|
||||
query.azureResourceGraph = { query: `$${multiVariable.name}` };
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return false when a variable is used in a different part of the query', () => {
|
||||
const query = createMockQuery();
|
||||
const templateSrv = new TemplateSrv();
|
||||
templateSrv.init([singleVariable]);
|
||||
|
||||
const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv);
|
||||
query.queryType = AzureQueryType.AzureResourceGraph;
|
||||
query.azureMonitor = { metricName: `$${singleVariable.name}` };
|
||||
expect(ds.targetContainsTemplate(query)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
ScopedVars,
|
||||
} from '@grafana/data';
|
||||
import { forkJoin, Observable, of } from 'rxjs';
|
||||
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import InsightsAnalyticsDatasource from './insights_analytics/insights_analytics_datasource';
|
||||
import { datasourceMigrations } from './utils/migrateQuery';
|
||||
import { map } from 'rxjs/operators';
|
||||
@ -131,6 +131,23 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
|
||||
return of({ state: LoadingState.Done, data: [] });
|
||||
}
|
||||
|
||||
targetContainsTemplate(query: AzureMonitorQuery) {
|
||||
if (query.subscription && this.templateSrv.variableExists(query.subscription)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let subQuery;
|
||||
if (query.queryType === AzureQueryType.AzureMonitor) {
|
||||
subQuery = JSON.stringify(query.azureMonitor);
|
||||
} else if (query.queryType === AzureQueryType.LogAnalytics) {
|
||||
subQuery = JSON.stringify(query.azureLogAnalytics);
|
||||
} else if (query.queryType === AzureQueryType.AzureResourceGraph) {
|
||||
subQuery = JSON.stringify([query.azureResourceGraph, query.subscriptions]);
|
||||
}
|
||||
|
||||
return !!subQuery && this.templateSrv.variableExists(subQuery);
|
||||
}
|
||||
|
||||
async annotationQuery(options: any) {
|
||||
return this.azureLogAnalyticsDatasource.annotationQuery(options);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user