mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Azure Monitor: Add support to migrate some queries with template variables (#51881)
This commit is contained in:
parent
f6f017edc2
commit
438c76252a
@ -1,7 +1,7 @@
|
|||||||
import { find, startsWith } from 'lodash';
|
import { find, startsWith } from 'lodash';
|
||||||
|
|
||||||
import { DataSourceInstanceSettings, ScopedVars } from '@grafana/data';
|
import { DataSourceInstanceSettings, ScopedVars } from '@grafana/data';
|
||||||
import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
|
import { DataSourceWithBackend, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||||
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
|
|
||||||
import { resourceTypeDisplayNames, supportedMetricNamespaces } from '../azureMetadata';
|
import { resourceTypeDisplayNames, supportedMetricNamespaces } from '../azureMetadata';
|
||||||
@ -42,11 +42,13 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
declare resourceGroup: string;
|
declare resourceGroup: string;
|
||||||
declare resourceName: string;
|
declare resourceName: string;
|
||||||
timeSrv: TimeSrv;
|
timeSrv: TimeSrv;
|
||||||
|
templateSrv: TemplateSrv;
|
||||||
|
|
||||||
constructor(private instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>) {
|
constructor(private instanceSettings: DataSourceInstanceSettings<AzureDataSourceJsonData>) {
|
||||||
super(instanceSettings);
|
super(instanceSettings);
|
||||||
|
|
||||||
this.timeSrv = getTimeSrv();
|
this.timeSrv = getTimeSrv();
|
||||||
|
this.templateSrv = getTemplateSrv();
|
||||||
this.defaultSubscriptionId = instanceSettings.jsonData.subscriptionId;
|
this.defaultSubscriptionId = instanceSettings.jsonData.subscriptionId;
|
||||||
|
|
||||||
const cloud = getAzureCloud(instanceSettings);
|
const cloud = getAzureCloud(instanceSettings);
|
||||||
@ -244,7 +246,8 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
|
||||||
this.resourcePath,
|
this.resourcePath,
|
||||||
this.apiPreviewVersion,
|
this.apiPreviewVersion,
|
||||||
this.replaceTemplateVariables(query)
|
this.replaceTemplateVariables(query),
|
||||||
|
this.templateSrv
|
||||||
);
|
);
|
||||||
return this.getResource(url)
|
return this.getResource(url)
|
||||||
.then((result: AzureMonitorMetricNamespacesResponse) => {
|
.then((result: AzureMonitorMetricNamespacesResponse) => {
|
||||||
@ -273,7 +276,8 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
this.resourcePath,
|
this.resourcePath,
|
||||||
this.apiVersion,
|
this.apiVersion,
|
||||||
this.replaceTemplateVariables(query)
|
this.replaceTemplateVariables(query),
|
||||||
|
this.templateSrv
|
||||||
);
|
);
|
||||||
return this.getResource(url).then((result: AzureMonitorMetricNamesResponse) => {
|
return this.getResource(url).then((result: AzureMonitorMetricNamesResponse) => {
|
||||||
return ResponseParser.parseResponseValues(result, 'name.localizedValue', 'name.value');
|
return ResponseParser.parseResponseValues(result, 'name.localizedValue', 'name.value');
|
||||||
@ -285,7 +289,8 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
|||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
this.resourcePath,
|
this.resourcePath,
|
||||||
this.apiVersion,
|
this.apiVersion,
|
||||||
this.replaceTemplateVariables(query)
|
this.replaceTemplateVariables(query),
|
||||||
|
this.templateSrv
|
||||||
);
|
);
|
||||||
return this.getResource(url).then((result: AzureMonitorMetricsMetadataResponse) => {
|
return this.getResource(url).then((result: AzureMonitorMetricsMetadataResponse) => {
|
||||||
return ResponseParser.parseMetadata(result, metricName);
|
return ResponseParser.parseMetadata(result, metricName);
|
||||||
|
@ -1,33 +1,96 @@
|
|||||||
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import UrlBuilder from './url_builder';
|
import UrlBuilder from './url_builder';
|
||||||
|
|
||||||
|
let replaceMock = jest.fn().mockImplementation((s: string) => s);
|
||||||
|
|
||||||
|
jest.mock('@grafana/runtime', () => {
|
||||||
|
const original = jest.requireActual('@grafana/runtime');
|
||||||
|
return {
|
||||||
|
...original,
|
||||||
|
getTemplateSrv: () => ({
|
||||||
|
replace: replaceMock,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
describe('AzureMonitorUrlBuilder', () => {
|
describe('AzureMonitorUrlBuilder', () => {
|
||||||
|
let templateSrv = getTemplateSrv();
|
||||||
describe('buildResourceUri', () => {
|
describe('buildResourceUri', () => {
|
||||||
it('builds a resource uri when the required properties are provided', () => {
|
it('builds a resource uri when the required properties are provided', () => {
|
||||||
expect(UrlBuilder.buildResourceUri('sub', 'group', 'Microsoft.NetApp/netAppAccounts', 'name')).toEqual(
|
expect(
|
||||||
'/subscriptions/sub/resourceGroups/group/providers/Microsoft.NetApp/netAppAccounts/name'
|
UrlBuilder.buildResourceUri('sub', 'group', 'Microsoft.NetApp/netAppAccounts', 'name', templateSrv)
|
||||||
);
|
).toEqual('/subscriptions/sub/resourceGroups/group/providers/Microsoft.NetApp/netAppAccounts/name');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('builds a resource uri correctly when a template variable is used as namespace', () => {
|
it('builds a resource uri correctly when a template variable is used as namespace', () => {
|
||||||
expect(UrlBuilder.buildResourceUri('sub', 'group', '$ns', 'name')).toEqual(
|
expect(UrlBuilder.buildResourceUri('sub', 'group', '$ns', 'name', templateSrv)).toEqual(
|
||||||
'/subscriptions/sub/resourceGroups/group/providers/$ns/name'
|
'/subscriptions/sub/resourceGroups/group/providers/$ns/name'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('builds a resource uri correctly when the namespace includes a storage sub-resource', () => {
|
it('builds a resource uri correctly when the namespace includes a storage sub-resource', () => {
|
||||||
expect(
|
expect(
|
||||||
UrlBuilder.buildResourceUri('sub', 'group', 'Microsoft.Storage/storageAccounts/tableServices', 'name')
|
UrlBuilder.buildResourceUri(
|
||||||
|
'sub',
|
||||||
|
'group',
|
||||||
|
'Microsoft.Storage/storageAccounts/tableServices',
|
||||||
|
'name',
|
||||||
|
templateSrv
|
||||||
|
)
|
||||||
).toEqual(
|
).toEqual(
|
||||||
'/subscriptions/sub/resourceGroups/group/providers/Microsoft.Storage/storageAccounts/name/tableServices/default'
|
'/subscriptions/sub/resourceGroups/group/providers/Microsoft.Storage/storageAccounts/name/tableServices/default'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when using template variables', () => {
|
||||||
|
replaceMock = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation((s: string) =>
|
||||||
|
s
|
||||||
|
.replace('$ns', 'Microsoft.Storage/storageAccounts')
|
||||||
|
.replace('$ns2', 'tableServices')
|
||||||
|
.replace('$rs', 'name')
|
||||||
|
.replace('$rs2', 'default')
|
||||||
|
);
|
||||||
|
templateSrv = getTemplateSrv();
|
||||||
|
|
||||||
|
it('builds a resource uri without specifying a subresource (default)', () => {
|
||||||
|
expect(UrlBuilder.buildResourceUri('sub', 'group', '$ns/tableServices', 'name', templateSrv)).toEqual(
|
||||||
|
'/subscriptions/sub/resourceGroups/group/providers/$ns/name/tableServices/default'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('builds a resource uri specifying a subresource (default)', () => {
|
||||||
|
expect(UrlBuilder.buildResourceUri('sub', 'group', '$ns/tableServices', 'name/default', templateSrv)).toEqual(
|
||||||
|
'/subscriptions/sub/resourceGroups/group/providers/$ns/name/tableServices/default'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('builds a resource uri specifying a resource template variable', () => {
|
||||||
|
expect(UrlBuilder.buildResourceUri('sub', 'group', '$ns/tableServices', '$rs/default', templateSrv)).toEqual(
|
||||||
|
'/subscriptions/sub/resourceGroups/group/providers/$ns/$rs/tableServices/default'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('builds a resource uri specifying multiple template variables', () => {
|
||||||
|
expect(UrlBuilder.buildResourceUri('sub', 'group', '$ns/$ns2', '$rs/$rs2', templateSrv)).toEqual(
|
||||||
|
'/subscriptions/sub/resourceGroups/group/providers/$ns/$rs/$ns2/$rs2'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when a resource uri is provided', () => {
|
describe('when a resource uri is provided', () => {
|
||||||
it('builds a getMetricNamesnamespace url', () => {
|
it('builds a getMetricNamesnamespace url', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
|
||||||
resourceUri: '/subscriptions/sub/resource-uri/resource',
|
'',
|
||||||
});
|
'2017-05-01-preview',
|
||||||
|
{
|
||||||
|
resourceUri: '/subscriptions/sub/resource-uri/resource',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
'/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
||||||
);
|
);
|
||||||
@ -36,10 +99,15 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when a resource uri and metric namespace is provided', () => {
|
describe('when a resource uri and metric namespace is provided', () => {
|
||||||
it('builds a getMetricNames url', () => {
|
it('builds a getMetricNames url', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
resourceUri: '/subscriptions/sub/resource-uri/resource',
|
'',
|
||||||
metricNamespace: 'Microsoft.Sql/servers',
|
'2017-05-01-preview',
|
||||||
});
|
{
|
||||||
|
resourceUri: '/subscriptions/sub/resource-uri/resource',
|
||||||
|
metricNamespace: 'Microsoft.Sql/servers',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Sql%2Fservers'
|
'/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Sql%2Fservers'
|
||||||
);
|
);
|
||||||
@ -49,12 +117,17 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
describe('Legacy query object', () => {
|
describe('Legacy query object', () => {
|
||||||
describe('when metric definition is Microsoft.NetApp/netAppAccounts/capacityPools/volumes', () => {
|
describe('when metric definition is Microsoft.NetApp/netAppAccounts/capacityPools/volumes', () => {
|
||||||
it('should build the getMetricNamespaces url in the even longer format', () => {
|
it('should build the getMetricNamespaces url in the even longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
|
{
|
||||||
resourceName: 'rn1/rn2/rn3',
|
subscription: 'sub1',
|
||||||
});
|
resourceGroup: 'rg',
|
||||||
|
metricDefinition: 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
|
||||||
|
resourceName: 'rn1/rn2/rn3',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.NetApp/netAppAccounts/rn1/capacityPools/rn2/volumes/rn3/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.NetApp/netAppAccounts/rn1/capacityPools/rn2/volumes/rn3/' +
|
||||||
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
||||||
@ -64,12 +137,17 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Sql/servers/databases', () => {
|
describe('when metric definition is Microsoft.Sql/servers/databases', () => {
|
||||||
it('should build the getMetricNamespaces url in the longer format', () => {
|
it('should build the getMetricNamespaces url in the longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Sql/servers/databases',
|
{
|
||||||
resourceName: 'rn1/rn2',
|
subscription: 'sub1',
|
||||||
});
|
resourceGroup: 'rg',
|
||||||
|
metricDefinition: 'Microsoft.Sql/servers/databases',
|
||||||
|
resourceName: 'rn1/rn2',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn1/databases/rn2/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn1/databases/rn2/' +
|
||||||
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
||||||
@ -79,12 +157,17 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Sql/servers', () => {
|
describe('when metric definition is Microsoft.Sql/servers', () => {
|
||||||
it('should build the getMetricNamespaces url in the shorter format', () => {
|
it('should build the getMetricNamespaces url in the shorter format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Sql/servers',
|
{
|
||||||
resourceName: 'rn',
|
subscription: 'sub1',
|
||||||
});
|
resourceGroup: 'rg',
|
||||||
|
metricDefinition: 'Microsoft.Sql/servers',
|
||||||
|
resourceName: 'rn',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn/' +
|
||||||
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
|
||||||
@ -94,13 +177,18 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.NetApp/netAppAccounts/capacityPools/volumes and the metricNamespace is default', () => {
|
describe('when metric definition is Microsoft.NetApp/netAppAccounts/capacityPools/volumes and the metricNamespace is default', () => {
|
||||||
it('should build the getMetricNames url in the even longer format', () => {
|
it('should build the getMetricNames url in the even longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
|
{
|
||||||
resourceName: 'rn1/rn2/rn3',
|
subscription: 'sub1',
|
||||||
metricNamespace: 'default',
|
resourceGroup: 'rg',
|
||||||
});
|
metricDefinition: 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
|
||||||
|
resourceName: 'rn1/rn2/rn3',
|
||||||
|
metricNamespace: 'default',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.NetApp/netAppAccounts/rn1/capacityPools/rn2/volumes/rn3/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.NetApp/netAppAccounts/rn1/capacityPools/rn2/volumes/rn3/' +
|
||||||
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
||||||
@ -110,13 +198,18 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Sql/servers/databases and the metricNamespace is default', () => {
|
describe('when metric definition is Microsoft.Sql/servers/databases and the metricNamespace is default', () => {
|
||||||
it('should build the getMetricNames url in the longer format', () => {
|
it('should build the getMetricNames url in the longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Sql/servers/databases',
|
{
|
||||||
resourceName: 'rn1/rn2',
|
subscription: 'sub1',
|
||||||
metricNamespace: 'default',
|
resourceGroup: 'rg',
|
||||||
});
|
metricDefinition: 'Microsoft.Sql/servers/databases',
|
||||||
|
resourceName: 'rn1/rn2',
|
||||||
|
metricNamespace: 'default',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn1/databases/rn2/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn1/databases/rn2/' +
|
||||||
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
||||||
@ -126,13 +219,18 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Sql/servers and the metricNamespace is default', () => {
|
describe('when metric definition is Microsoft.Sql/servers and the metricNamespace is default', () => {
|
||||||
it('should build the getMetricNames url in the shorter format', () => {
|
it('should build the getMetricNames url in the shorter format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Sql/servers',
|
{
|
||||||
resourceName: 'rn',
|
subscription: 'sub1',
|
||||||
metricNamespace: 'default',
|
resourceGroup: 'rg',
|
||||||
});
|
metricDefinition: 'Microsoft.Sql/servers',
|
||||||
|
resourceName: 'rn',
|
||||||
|
metricNamespace: 'default',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn/' +
|
||||||
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
||||||
@ -142,13 +240,18 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Storage/storageAccounts/blobServices and the metricNamespace is default', () => {
|
describe('when metric definition is Microsoft.Storage/storageAccounts/blobServices and the metricNamespace is default', () => {
|
||||||
it('should build the getMetricNames url in the longer format', () => {
|
it('should build the getMetricNames url in the longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Storage/storageAccounts/blobServices',
|
{
|
||||||
resourceName: 'rn1/default',
|
subscription: 'sub1',
|
||||||
metricNamespace: 'default',
|
resourceGroup: 'rg',
|
||||||
});
|
metricDefinition: 'Microsoft.Storage/storageAccounts/blobServices',
|
||||||
|
resourceName: 'rn1/default',
|
||||||
|
metricNamespace: 'default',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/blobServices/default/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/blobServices/default/' +
|
||||||
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
||||||
@ -158,13 +261,18 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Storage/storageAccounts/fileServices and the metricNamespace is default', () => {
|
describe('when metric definition is Microsoft.Storage/storageAccounts/fileServices and the metricNamespace is default', () => {
|
||||||
it('should build the getMetricNames url in the longer format', () => {
|
it('should build the getMetricNames url in the longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Storage/storageAccounts/fileServices',
|
{
|
||||||
resourceName: 'rn1/default',
|
subscription: 'sub1',
|
||||||
metricNamespace: 'default',
|
resourceGroup: 'rg',
|
||||||
});
|
metricDefinition: 'Microsoft.Storage/storageAccounts/fileServices',
|
||||||
|
resourceName: 'rn1/default',
|
||||||
|
metricNamespace: 'default',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/fileServices/default/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/fileServices/default/' +
|
||||||
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
||||||
@ -174,13 +282,18 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Storage/storageAccounts/tableServices and the metricNamespace is default', () => {
|
describe('when metric definition is Microsoft.Storage/storageAccounts/tableServices and the metricNamespace is default', () => {
|
||||||
it('should build the getMetricNames url in the longer format', () => {
|
it('should build the getMetricNames url in the longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Storage/storageAccounts/tableServices',
|
{
|
||||||
resourceName: 'rn1/default',
|
subscription: 'sub1',
|
||||||
metricNamespace: 'default',
|
resourceGroup: 'rg',
|
||||||
});
|
metricDefinition: 'Microsoft.Storage/storageAccounts/tableServices',
|
||||||
|
resourceName: 'rn1/default',
|
||||||
|
metricNamespace: 'default',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/tableServices/default/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/tableServices/default/' +
|
||||||
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
||||||
@ -190,13 +303,18 @@ describe('AzureMonitorUrlBuilder', () => {
|
|||||||
|
|
||||||
describe('when metric definition is Microsoft.Storage/storageAccounts/queueServices and the metricNamespace is default', () => {
|
describe('when metric definition is Microsoft.Storage/storageAccounts/queueServices and the metricNamespace is default', () => {
|
||||||
it('should build the getMetricNames url in the longer format', () => {
|
it('should build the getMetricNames url in the longer format', () => {
|
||||||
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
|
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
|
||||||
subscription: 'sub1',
|
'',
|
||||||
resourceGroup: 'rg',
|
'2017-05-01-preview',
|
||||||
metricDefinition: 'Microsoft.Storage/storageAccounts/queueServices',
|
{
|
||||||
resourceName: 'rn1/default',
|
subscription: 'sub1',
|
||||||
metricNamespace: 'default',
|
resourceGroup: 'rg',
|
||||||
});
|
metricDefinition: 'Microsoft.Storage/storageAccounts/queueServices',
|
||||||
|
resourceName: 'rn1/default',
|
||||||
|
metricNamespace: 'default',
|
||||||
|
},
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
expect(url).toBe(
|
expect(url).toBe(
|
||||||
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/queueServices/default/' +
|
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/queueServices/default/' +
|
||||||
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { TemplateSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import { GetMetricNamespacesQuery, GetMetricNamesQuery } from '../types';
|
import { GetMetricNamespacesQuery, GetMetricNamesQuery } from '../types';
|
||||||
|
|
||||||
export default class UrlBuilder {
|
export default class UrlBuilder {
|
||||||
@ -5,40 +7,65 @@ export default class UrlBuilder {
|
|||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroup: string,
|
resourceGroup: string,
|
||||||
metricDefinition: string,
|
metricDefinition: string,
|
||||||
resourceName: string
|
resourceName: string,
|
||||||
|
templateSrv: TemplateSrv
|
||||||
) {
|
) {
|
||||||
|
const metricDefinitionProcessed = templateSrv.replace(metricDefinition);
|
||||||
const metricDefinitionArray = metricDefinition.split('/');
|
const metricDefinitionArray = metricDefinition.split('/');
|
||||||
|
const resourceNameProcessed = templateSrv.replace(resourceName);
|
||||||
const resourceNameArray = resourceName.split('/');
|
const resourceNameArray = resourceName.split('/');
|
||||||
const provider = metricDefinitionArray.shift();
|
const provider = metricDefinitionArray.shift();
|
||||||
const urlArray = ['/subscriptions', subscriptionId, 'resourceGroups', resourceGroup, 'providers', provider];
|
const urlArray = ['/subscriptions', subscriptionId, 'resourceGroups', resourceGroup, 'providers', provider];
|
||||||
if (metricDefinition.startsWith('Microsoft.Storage/storageAccounts/') && resourceNameArray.at(-1) !== 'default') {
|
|
||||||
|
if (
|
||||||
|
metricDefinitionProcessed.startsWith('Microsoft.Storage/storageAccounts/') &&
|
||||||
|
!resourceNameProcessed.endsWith('default')
|
||||||
|
) {
|
||||||
resourceNameArray.push('default');
|
resourceNameArray.push('default');
|
||||||
}
|
}
|
||||||
if (metricDefinitionArray.length > 0) {
|
|
||||||
for (const i in metricDefinitionArray) {
|
if (resourceNameArray.length > metricDefinitionArray.length) {
|
||||||
urlArray.push(metricDefinitionArray[i]);
|
const parentResource = resourceNameArray.shift();
|
||||||
urlArray.push(resourceNameArray[i]);
|
urlArray.push(parentResource);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
urlArray.push(resourceNameArray[0]);
|
for (const i in metricDefinitionArray) {
|
||||||
|
urlArray.push(metricDefinitionArray[i]);
|
||||||
|
urlArray.push(resourceNameArray[i]);
|
||||||
}
|
}
|
||||||
return urlArray.join('/');
|
return urlArray.join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
static buildAzureMonitorGetMetricNamespacesUrl(baseUrl: string, apiVersion: string, query: GetMetricNamespacesQuery) {
|
static buildAzureMonitorGetMetricNamespacesUrl(
|
||||||
|
baseUrl: string,
|
||||||
|
apiVersion: string,
|
||||||
|
query: GetMetricNamespacesQuery,
|
||||||
|
templateSrv: TemplateSrv
|
||||||
|
) {
|
||||||
let resourceUri: string;
|
let resourceUri: string;
|
||||||
|
|
||||||
if ('resourceUri' in query) {
|
if ('resourceUri' in query) {
|
||||||
resourceUri = query.resourceUri;
|
resourceUri = query.resourceUri;
|
||||||
} else {
|
} else {
|
||||||
const { subscription, resourceGroup, metricDefinition, resourceName } = query;
|
const { subscription, resourceGroup, metricDefinition, resourceName } = query;
|
||||||
resourceUri = UrlBuilder.buildResourceUri(subscription, resourceGroup, metricDefinition, resourceName);
|
resourceUri = UrlBuilder.buildResourceUri(
|
||||||
|
subscription,
|
||||||
|
resourceGroup,
|
||||||
|
metricDefinition,
|
||||||
|
resourceName,
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${baseUrl}${resourceUri}/providers/microsoft.insights/metricNamespaces?api-version=${apiVersion}`;
|
return `${baseUrl}${resourceUri}/providers/microsoft.insights/metricNamespaces?api-version=${apiVersion}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static buildAzureMonitorGetMetricNamesUrl(baseUrl: string, apiVersion: string, query: GetMetricNamesQuery) {
|
static buildAzureMonitorGetMetricNamesUrl(
|
||||||
|
baseUrl: string,
|
||||||
|
apiVersion: string,
|
||||||
|
query: GetMetricNamesQuery,
|
||||||
|
templateSrv: TemplateSrv
|
||||||
|
) {
|
||||||
let resourceUri: string;
|
let resourceUri: string;
|
||||||
const { metricNamespace } = query;
|
const { metricNamespace } = query;
|
||||||
|
|
||||||
@ -46,7 +73,13 @@ export default class UrlBuilder {
|
|||||||
resourceUri = query.resourceUri;
|
resourceUri = query.resourceUri;
|
||||||
} else {
|
} else {
|
||||||
const { subscription, resourceGroup, metricDefinition, resourceName } = query;
|
const { subscription, resourceGroup, metricDefinition, resourceName } = query;
|
||||||
resourceUri = UrlBuilder.buildResourceUri(subscription, resourceGroup, metricDefinition, resourceName);
|
resourceUri = UrlBuilder.buildResourceUri(
|
||||||
|
subscription,
|
||||||
|
resourceGroup,
|
||||||
|
metricDefinition,
|
||||||
|
resourceName,
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -2,6 +2,8 @@ import deepEqual from 'fast-deep-equal';
|
|||||||
import { defaults } from 'lodash';
|
import { defaults } from 'lodash';
|
||||||
import { useEffect, useMemo } from 'react';
|
import { useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import { AzureMonitorQuery, AzureQueryType } from '../../types';
|
import { AzureMonitorQuery, AzureQueryType } from '../../types';
|
||||||
import migrateQuery from '../../utils/migrateQuery';
|
import migrateQuery from '../../utils/migrateQuery';
|
||||||
|
|
||||||
@ -12,7 +14,7 @@ const DEFAULT_QUERY = {
|
|||||||
const prepareQuery = (query: AzureMonitorQuery) => {
|
const prepareQuery = (query: AzureMonitorQuery) => {
|
||||||
// Note: _.defaults does not apply default values deeply.
|
// Note: _.defaults does not apply default values deeply.
|
||||||
const withDefaults = defaults({}, query, DEFAULT_QUERY);
|
const withDefaults = defaults({}, query, DEFAULT_QUERY);
|
||||||
const migratedQuery = migrateQuery(withDefaults);
|
const migratedQuery = migrateQuery(withDefaults, getTemplateSrv());
|
||||||
|
|
||||||
// If we didn't make any changes to the object, then return the original object to keep the
|
// If we didn't make any changes to the object, then return the original object to keep the
|
||||||
// identity the same, and not trigger any other useEffects or anything.
|
// identity the same, and not trigger any other useEffects or anything.
|
||||||
|
@ -70,7 +70,7 @@ export default class Datasource extends DataSourceWithBackend<AzureMonitorQuery,
|
|||||||
|
|
||||||
for (const baseTarget of options.targets) {
|
for (const baseTarget of options.targets) {
|
||||||
// Migrate old query structures
|
// Migrate old query structures
|
||||||
const target = datasourceMigrations(baseTarget);
|
const target = datasourceMigrations(baseTarget, this.templateSrv);
|
||||||
|
|
||||||
// Skip hidden or invalid queries or ones without properties
|
// Skip hidden or invalid queries or ones without properties
|
||||||
if (!target.queryType || target.hide || !hasQueryForType(target)) {
|
if (!target.queryType || target.hide || !hasQueryForType(target)) {
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import { AzureMetricDimension, AzureMonitorQuery, AzureQueryType } from '../types';
|
import { AzureMetricDimension, AzureMonitorQuery, AzureQueryType } from '../types';
|
||||||
|
|
||||||
import migrateQuery from './migrateQuery';
|
import migrateQuery from './migrateQuery';
|
||||||
|
|
||||||
|
let replaceMock = jest.fn().mockImplementation((s: string) => s);
|
||||||
|
jest.mock('@grafana/runtime', () => {
|
||||||
|
const original = jest.requireActual('@grafana/runtime');
|
||||||
|
return {
|
||||||
|
...original,
|
||||||
|
getTemplateSrv: () => ({
|
||||||
|
replace: replaceMock,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let templateSrv = getTemplateSrv();
|
||||||
|
|
||||||
const azureMonitorQueryV7 = {
|
const azureMonitorQueryV7 = {
|
||||||
appInsights: { dimension: [], metricName: 'select', timeGrain: 'auto' },
|
appInsights: { dimension: [], metricName: 'select', timeGrain: 'auto' },
|
||||||
azureLogAnalytics: {
|
azureLogAnalytics: {
|
||||||
@ -82,7 +97,7 @@ const modernMetricsQuery: AzureMonitorQuery = {
|
|||||||
|
|
||||||
describe('AzureMonitor: migrateQuery', () => {
|
describe('AzureMonitor: migrateQuery', () => {
|
||||||
it('modern queries should not change', () => {
|
it('modern queries should not change', () => {
|
||||||
const result = migrateQuery(modernMetricsQuery);
|
const result = migrateQuery(modernMetricsQuery, templateSrv);
|
||||||
|
|
||||||
// MUST use .toBe because we want to assert that the identity of unmigrated queries remains the same
|
// MUST use .toBe because we want to assert that the identity of unmigrated queries remains the same
|
||||||
expect(modernMetricsQuery).toBe(result);
|
expect(modernMetricsQuery).toBe(result);
|
||||||
@ -90,7 +105,7 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
|
|
||||||
describe('migrating from a v7 query to the latest query version', () => {
|
describe('migrating from a v7 query to the latest query version', () => {
|
||||||
it('should build a resource uri', () => {
|
it('should build a resource uri', () => {
|
||||||
const result = migrateQuery(azureMonitorQueryV7);
|
const result = migrateQuery(azureMonitorQueryV7, templateSrv);
|
||||||
expect(result).toMatchObject(
|
expect(result).toMatchObject(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
azureMonitor: expect.objectContaining({
|
azureMonitor: expect.objectContaining({
|
||||||
@ -104,7 +119,7 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
|
|
||||||
describe('migrating from a v8 query to the latest query version', () => {
|
describe('migrating from a v8 query to the latest query version', () => {
|
||||||
it('should build a resource uri', () => {
|
it('should build a resource uri', () => {
|
||||||
const result = migrateQuery(azureMonitorQueryV8);
|
const result = migrateQuery(azureMonitorQueryV8, templateSrv);
|
||||||
expect(result).toMatchObject(
|
expect(result).toMatchObject(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
azureMonitor: expect.objectContaining({
|
azureMonitor: expect.objectContaining({
|
||||||
@ -114,6 +129,20 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not build a resource uri with an unsupported template variable', () => {
|
||||||
|
replaceMock = jest.fn().mockImplementation((s: string) => s.replace('$ns', 'Microsoft.Storage/storageAccounts'));
|
||||||
|
templateSrv = getTemplateSrv();
|
||||||
|
const query = {
|
||||||
|
...azureMonitorQueryV8,
|
||||||
|
azureMonitor: {
|
||||||
|
...azureMonitorQueryV8,
|
||||||
|
metricDefinition: '$ns',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const result = migrateQuery(query, templateSrv);
|
||||||
|
expect(result.azureMonitor?.resourceUri).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('migrating from a v9 query to the latest query version', () => {
|
describe('migrating from a v9 query to the latest query version', () => {
|
||||||
@ -121,7 +150,7 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
const dimensionFilters: AzureMetricDimension[] = [
|
const dimensionFilters: AzureMetricDimension[] = [
|
||||||
{ dimension: 'TestDimension', operator: 'eq', filters: ['testFilter'] },
|
{ dimension: 'TestDimension', operator: 'eq', filters: ['testFilter'] },
|
||||||
];
|
];
|
||||||
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } });
|
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } }, templateSrv);
|
||||||
expect(result).toMatchObject(
|
expect(result).toMatchObject(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
azureMonitor: expect.objectContaining({
|
azureMonitor: expect.objectContaining({
|
||||||
@ -132,7 +161,7 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
});
|
});
|
||||||
it('correctly updates old filter containing wildcard', () => {
|
it('correctly updates old filter containing wildcard', () => {
|
||||||
const dimensionFilters: AzureMetricDimension[] = [{ dimension: 'TestDimension', operator: 'eq', filter: '*' }];
|
const dimensionFilters: AzureMetricDimension[] = [{ dimension: 'TestDimension', operator: 'eq', filter: '*' }];
|
||||||
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } });
|
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } }, templateSrv);
|
||||||
expect(result).toMatchObject(
|
expect(result).toMatchObject(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
azureMonitor: expect.objectContaining({
|
azureMonitor: expect.objectContaining({
|
||||||
@ -145,7 +174,7 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
});
|
});
|
||||||
it('correctly updates old filter containing value', () => {
|
it('correctly updates old filter containing value', () => {
|
||||||
const dimensionFilters: AzureMetricDimension[] = [{ dimension: 'TestDimension', operator: 'eq', filter: 'test' }];
|
const dimensionFilters: AzureMetricDimension[] = [{ dimension: 'TestDimension', operator: 'eq', filter: 'test' }];
|
||||||
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } });
|
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } }, templateSrv);
|
||||||
expect(result).toMatchObject(
|
expect(result).toMatchObject(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
azureMonitor: expect.objectContaining({
|
azureMonitor: expect.objectContaining({
|
||||||
@ -160,7 +189,7 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
const dimensionFilters: AzureMetricDimension[] = [
|
const dimensionFilters: AzureMetricDimension[] = [
|
||||||
{ dimension: 'TestDimension', operator: 'eq', filter: '*', filters: ['testFilter'] },
|
{ dimension: 'TestDimension', operator: 'eq', filter: '*', filters: ['testFilter'] },
|
||||||
];
|
];
|
||||||
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } });
|
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } }, templateSrv);
|
||||||
expect(result).toMatchObject(
|
expect(result).toMatchObject(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
azureMonitor: expect.objectContaining({
|
azureMonitor: expect.objectContaining({
|
||||||
@ -179,7 +208,7 @@ describe('AzureMonitor: migrateQuery', () => {
|
|||||||
const dimensionFilters: AzureMetricDimension[] = [
|
const dimensionFilters: AzureMetricDimension[] = [
|
||||||
{ dimension: 'TestDimension', operator: 'eq', filter: 'testFilter', filters: ['testFilter'] },
|
{ dimension: 'TestDimension', operator: 'eq', filter: 'testFilter', filters: ['testFilter'] },
|
||||||
];
|
];
|
||||||
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } });
|
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } }, templateSrv);
|
||||||
expect(result).toMatchObject(
|
expect(result).toMatchObject(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
azureMonitor: expect.objectContaining({
|
azureMonitor: expect.objectContaining({
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { TemplateSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import UrlBuilder from '../azure_monitor/url_builder';
|
import UrlBuilder from '../azure_monitor/url_builder';
|
||||||
import { setKustoQuery } from '../components/LogsQueryEditor/setQueryValue';
|
import { setKustoQuery } from '../components/LogsQueryEditor/setQueryValue';
|
||||||
import {
|
import {
|
||||||
@ -9,7 +11,7 @@ import { AzureMetricDimension, AzureMonitorQuery, AzureQueryType } from '../type
|
|||||||
|
|
||||||
const OLD_DEFAULT_DROPDOWN_VALUE = 'select';
|
const OLD_DEFAULT_DROPDOWN_VALUE = 'select';
|
||||||
|
|
||||||
export default function migrateQuery(query: AzureMonitorQuery): AzureMonitorQuery {
|
export default function migrateQuery(query: AzureMonitorQuery, templateSrv: TemplateSrv): AzureMonitorQuery {
|
||||||
let workingQuery = query;
|
let workingQuery = query;
|
||||||
|
|
||||||
// The old angular controller also had a `migrateApplicationInsightsKeys` migraiton that
|
// The old angular controller also had a `migrateApplicationInsightsKeys` migraiton that
|
||||||
@ -21,7 +23,7 @@ export default function migrateQuery(query: AzureMonitorQuery): AzureMonitorQuer
|
|||||||
workingQuery = migrateLogAnalyticsToFromTimes(workingQuery);
|
workingQuery = migrateLogAnalyticsToFromTimes(workingQuery);
|
||||||
workingQuery = migrateToDefaultNamespace(workingQuery);
|
workingQuery = migrateToDefaultNamespace(workingQuery);
|
||||||
workingQuery = migrateDimensionToDimensionFilter(workingQuery);
|
workingQuery = migrateDimensionToDimensionFilter(workingQuery);
|
||||||
workingQuery = migrateResourceUri(workingQuery);
|
workingQuery = migrateResourceUri(workingQuery, templateSrv);
|
||||||
workingQuery = migrateDimensionFilterToArray(workingQuery);
|
workingQuery = migrateDimensionFilterToArray(workingQuery);
|
||||||
|
|
||||||
return workingQuery;
|
return workingQuery;
|
||||||
@ -96,7 +98,7 @@ function migrateDimensionToDimensionFilter(query: AzureMonitorQuery): AzureMonit
|
|||||||
// Azure Monitor metric queries prior to Grafana version 9 did not include a `resourceUri`.
|
// Azure Monitor metric queries prior to Grafana version 9 did not include a `resourceUri`.
|
||||||
// The resourceUri was previously constructed with the subscription id, resource group,
|
// The resourceUri was previously constructed with the subscription id, resource group,
|
||||||
// metric definition (a.k.a. resource type), and the resource name.
|
// metric definition (a.k.a. resource type), and the resource name.
|
||||||
function migrateResourceUri(query: AzureMonitorQuery): AzureMonitorQuery {
|
function migrateResourceUri(query: AzureMonitorQuery, templateSrv: TemplateSrv): AzureMonitorQuery {
|
||||||
const azureMonitorQuery = query.azureMonitor;
|
const azureMonitorQuery = query.azureMonitor;
|
||||||
|
|
||||||
if (!azureMonitorQuery || azureMonitorQuery.resourceUri) {
|
if (!azureMonitorQuery || azureMonitorQuery.resourceUri) {
|
||||||
@ -109,11 +111,28 @@ function migrateResourceUri(query: AzureMonitorQuery): AzureMonitorQuery {
|
|||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metricDefinition.includes('$') || resourceName.includes('$')) {
|
const metricDefinitionArray = metricDefinition.split('/');
|
||||||
|
if (metricDefinitionArray.some((p) => templateSrv.replace(p).split('/').length > 2)) {
|
||||||
|
// If a metric definition includes template variable with a subresource e.g.
|
||||||
|
// Microsoft.Storage/storageAccounts/libraries, it's not possible to generate a valid
|
||||||
|
// resource URI
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceUri = UrlBuilder.buildResourceUri(subscription, resourceGroup, metricDefinition, resourceName);
|
const resourceNameArray = resourceName.split('/');
|
||||||
|
if (resourceNameArray.some((p) => templateSrv.replace(p).split('/').length > 1)) {
|
||||||
|
// If a resource name includes template variable with a subresource e.g.
|
||||||
|
// abc123/def456, it's not possible to generate a valid resource URI
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resourceUri = UrlBuilder.buildResourceUri(
|
||||||
|
subscription,
|
||||||
|
resourceGroup,
|
||||||
|
metricDefinition,
|
||||||
|
resourceName,
|
||||||
|
templateSrv
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...query,
|
...query,
|
||||||
@ -163,7 +182,7 @@ function migrateDimensionFilterToArray(query: AzureMonitorQuery): AzureMonitorQu
|
|||||||
|
|
||||||
// datasource.ts also contains some migrations, which have been moved to here. Unsure whether
|
// datasource.ts also contains some migrations, which have been moved to here. Unsure whether
|
||||||
// they should also do all the other migrations...
|
// they should also do all the other migrations...
|
||||||
export function datasourceMigrations(query: AzureMonitorQuery): AzureMonitorQuery {
|
export function datasourceMigrations(query: AzureMonitorQuery, templateSrv: TemplateSrv): AzureMonitorQuery {
|
||||||
let workingQuery = query;
|
let workingQuery = query;
|
||||||
|
|
||||||
if (!workingQuery.queryType) {
|
if (!workingQuery.queryType) {
|
||||||
@ -175,7 +194,7 @@ export function datasourceMigrations(query: AzureMonitorQuery): AzureMonitorQuer
|
|||||||
|
|
||||||
if (workingQuery.queryType === AzureQueryType.AzureMonitor && workingQuery.azureMonitor) {
|
if (workingQuery.queryType === AzureQueryType.AzureMonitor && workingQuery.azureMonitor) {
|
||||||
workingQuery = migrateDimensionToDimensionFilter(workingQuery);
|
workingQuery = migrateDimensionToDimensionFilter(workingQuery);
|
||||||
workingQuery = migrateResourceUri(workingQuery);
|
workingQuery = migrateResourceUri(workingQuery, templateSrv);
|
||||||
workingQuery = migrateDimensionFilterToArray(workingQuery);
|
workingQuery = migrateDimensionFilterToArray(workingQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user