diff --git a/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.test.ts b/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.test.ts index 637ddbd8dfc..0f84b62322a 100644 --- a/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.test.ts +++ b/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.test.ts @@ -183,6 +183,47 @@ describe('AzureMonitorDatasource', () => { }, }); }); + + it('should migrate legacy properties before interpolation', () => { + templateSrv.init([ + { + id: 'resourcegroup', + name: 'resourcegroup', + current: { + value: `test-rg`, + }, + }, + { + id: 'resourcename', + name: 'resourcename', + current: { + value: `test-resource`, + }, + }, + { + id: 'metric', + name: 'metric', + current: { + value: `test-ns`, + }, + }, + ]); + const query = createMockQuery({ + azureMonitor: { + metricDefinition: '$metric', + resourceGroup: '$resourcegroup', + resourceName: '$resourcename', + metricNamespace: undefined, + }, + }); + const templatedQuery = ctx.ds.azureMonitorDatasource.applyTemplateVariables(query, {}); + expect(templatedQuery).toMatchObject({ + azureMonitor: { + metricNamespace: 'test-ns', + resources: [{ resourceGroup: 'test-rg', resourceName: 'test-resource' }], + }, + }); + }); }); describe('When performing getMetricNamespaces', () => { diff --git a/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.ts b/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.ts index 1eb89ab56d3..5621e34d3cc 100644 --- a/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.ts +++ b/public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.ts @@ -84,29 +84,46 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend this.replaceTemplateVariables(r, scopedVars)).flat(); - const metricNamespace = templateSrv.replace(item.metricNamespace, scopedVars); - const customNamespace = templateSrv.replace(item.customNamespace, scopedVars); - const timeGrain = templateSrv.replace((item.timeGrain || '').toString(), scopedVars); - const aggregation = templateSrv.replace(item.aggregation, scopedVars); - const top = templateSrv.replace(item.top || '', scopedVars); + // These properties need to be replaced pre-migration to ensure values are correctly interpolated + if (preMigrationQuery.resourceUri) { + preMigrationQuery.resourceUri = templateSrv.replace(preMigrationQuery.resourceUri, scopedVars); + } + if (preMigrationQuery.metricDefinition) { + preMigrationQuery.metricDefinition = templateSrv.replace(preMigrationQuery.metricDefinition, scopedVars); + } - const dimensionFilters = (item.dimensionFilters ?? []) + // fix for timeGrainUnit which is a deprecated/removed field name + if (preMigrationQuery.timeGrain && preMigrationQuery.timeGrainUnit && preMigrationQuery.timeGrain !== 'auto') { + preMigrationQuery.timeGrain = TimegrainConverter.createISO8601Duration( + preMigrationQuery.timeGrain, + preMigrationQuery.timeGrainUnit + ); + } + + const migratedTarget = migrateQuery(target); + const migratedQuery = migratedTarget.azureMonitor; + // This should never be triggered because the above error would've been thrown + if (!migratedQuery) { + throw new Error('Query is not a valid Azure Monitor Metrics query'); + } + + const subscriptionId = templateSrv.replace(migratedTarget.subscription || this.defaultSubscriptionId, scopedVars); + const resources = migratedQuery.resources?.map((r) => this.replaceTemplateVariables(r, scopedVars)).flat(); + const metricNamespace = templateSrv.replace(migratedQuery.metricNamespace, scopedVars); + const customNamespace = templateSrv.replace(migratedQuery.customNamespace, scopedVars); + const timeGrain = templateSrv.replace((migratedQuery.timeGrain || '').toString(), scopedVars); + const aggregation = templateSrv.replace(migratedQuery.aggregation, scopedVars); + const top = templateSrv.replace(migratedQuery.top || '', scopedVars); + + const dimensionFilters = (migratedQuery.dimensionFilters ?? []) .filter((f) => f.dimension && f.dimension !== 'None') .map((f) => { const filters = f.filters?.map((filter) => templateSrv.replace(filter ?? '', scopedVars)); @@ -118,32 +135,26 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend> { diff --git a/public/app/plugins/datasource/azuremonitor/utils/migrateQuery.ts b/public/app/plugins/datasource/azuremonitor/utils/migrateQuery.ts index 843712c87aa..536660a342d 100644 --- a/public/app/plugins/datasource/azuremonitor/utils/migrateQuery.ts +++ b/public/app/plugins/datasource/azuremonitor/utils/migrateQuery.ts @@ -25,7 +25,7 @@ export default function migrateQuery(query: AzureMonitorQuery): AzureMonitorQuer workingQuery = migrateToDefaultNamespace(workingQuery); workingQuery = migrateDimensionToDimensionFilter(workingQuery); workingQuery = migrateDimensionFilterToArray(workingQuery); - workingQuery = migrateDimensionToResourceObj(workingQuery); + workingQuery = migrateResourceUriToResourceObj(workingQuery); } if (workingQuery.azureMonitor?.resourceGroup || workingQuery.azureMonitor?.resourceName) { @@ -154,7 +154,7 @@ function migrateDimensionFilterToArray(query: AzureMonitorQuery): AzureMonitorQu return query; } -function migrateDimensionToResourceObj(query: AzureMonitorQuery): AzureMonitorQuery { +function migrateResourceUriToResourceObj(query: AzureMonitorQuery): AzureMonitorQuery { if (query.azureMonitor?.resourceUri && !query.azureMonitor.resourceUri.startsWith('$')) { const details = parseResourceDetails(query.azureMonitor.resourceUri); const isWellFormedUri = details?.subscription && details?.resourceGroup && details?.resourceName;