Skip to content

Commit

Permalink
AzureMonitor: Ensure legacy properties containing template variables …
Browse files Browse the repository at this point in the history
…are correctly migrated (#68697)

* Update migration ordering

- Update migration in applyTemplateVariables to account for interpolation from expression datasource
- Update mock to ensure overrides are passed through correctly
- Update tests
- Update migrateQuery function name for clarity

* Fix tests

* Remove comment
  • Loading branch information
aangelisc committed May 22, 2023
1 parent bca8428 commit 0be29b4
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,29 +84,46 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
}

applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): AzureMonitorQuery {
const item = target.azureMonitor;
const preMigrationQuery = target.azureMonitor;

if (!item) {
// return target;
if (!preMigrationQuery) {
throw new Error('Query is not a valid Azure Monitor Metrics query');
}

const templateSrv = getTemplateSrv();

// 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);
}

// fix for timeGrainUnit which is a deprecated/removed field name
if (item.timeGrain && item.timeGrainUnit && item.timeGrain !== 'auto') {
item.timeGrain = TimegrainConverter.createISO8601Duration(item.timeGrain, item.timeGrainUnit);
if (preMigrationQuery.timeGrain && preMigrationQuery.timeGrainUnit && preMigrationQuery.timeGrain !== 'auto') {
preMigrationQuery.timeGrain = TimegrainConverter.createISO8601Duration(
preMigrationQuery.timeGrain,
preMigrationQuery.timeGrainUnit
);
}

const templateSrv = getTemplateSrv();
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(target.subscription || this.defaultSubscriptionId, scopedVars);
const resources = item.resources?.map((r) => 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);
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 = (item.dimensionFilters ?? [])
const dimensionFilters = (migratedQuery.dimensionFilters ?? [])
.filter((f) => f.dimension && f.dimension !== 'None')
.map((f) => {
const filters = f.filters?.map((filter) => templateSrv.replace(filter ?? '', scopedVars));
Expand All @@ -118,32 +135,26 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
});

const azMonitorQuery: AzureMetricQuery = {
...item,
...migratedQuery,
resources,
metricNamespace,
customNamespace,
timeGrain,
allowedTimeGrainsMs: item.allowedTimeGrainsMs,
metricName: templateSrv.replace(item.metricName, scopedVars),
region: templateSrv.replace(item.region, scopedVars),
allowedTimeGrainsMs: migratedQuery.allowedTimeGrainsMs,
metricName: templateSrv.replace(migratedQuery.metricName, scopedVars),
region: templateSrv.replace(migratedQuery.region, scopedVars),
aggregation: aggregation,
dimensionFilters,
top: top || '10',
alias: item.alias,
alias: migratedQuery.alias,
};
if (item.metricDefinition) {
azMonitorQuery.metricDefinition = templateSrv.replace(item.metricDefinition, scopedVars);
}
if (item.resourceUri) {
azMonitorQuery.resourceUri = templateSrv.replace(item.resourceUri, scopedVars);
}

return migrateQuery({
return {
...target,
subscription: subscriptionId,
queryType: AzureQueryType.AzureMonitor,
azureMonitor: azMonitorQuery,
});
};
}

async getSubscriptions(): Promise<Array<{ text: string; value: string }>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 0be29b4

Please sign in to comment.