diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.test.tsx
index 6291edb1814..a25a4868ca6 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.test.tsx
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.test.tsx
@@ -3,7 +3,6 @@ import userEvent from '@testing-library/user-event';
import React from 'react';
import { select, openMenu } from 'react-select-event';
-import * as grafanaRuntime from '@grafana/runtime';
import * as ui from '@grafana/ui';
import createMockDatasource from '../../__mocks__/datasource';
@@ -41,16 +40,11 @@ const defaultProps = {
}),
};
-const originalConfigValue = grafanaRuntime.config.featureToggles.azTemplateVars;
-beforeEach(() => {
- // reset config
- grafanaRuntime.config.featureToggles.azTemplateVars = originalConfigValue;
-});
-
describe('VariableEditor:', () => {
- it('can select a query type', async () => {
+ it('can view a legacy Grafana query function', async () => {
const onChange = jest.fn();
- const { rerender } = render();
+ const legacyQuery = { ...defaultProps.query, queryType: AzureQueryType.GrafanaTemplateVariableFn };
+ render();
await waitFor(() => screen.getByLabelText('select query type'));
expect(screen.getByLabelText('select query type')).toBeInTheDocument();
screen.getByLabelText('select query type').click();
@@ -62,10 +56,6 @@ describe('VariableEditor:', () => {
queryType: AzureQueryType.GrafanaTemplateVariableFn,
})
);
- const newQuery = onChange.mock.calls.at(-1)[0];
- rerender();
- expect(screen.queryByText('Logs')).not.toBeInTheDocument();
- expect(screen.queryByText('Grafana Query Function')).toBeInTheDocument();
});
describe('log queries:', () => {
it('should render', async () => {
@@ -157,22 +147,6 @@ describe('VariableEditor:', () => {
rerender();
await waitFor(() => expect(screen.getByText(text)).toBeInTheDocument());
};
- beforeEach(() => {
- grafanaRuntime.config.featureToggles.azTemplateVars = true;
- });
-
- it('should show the new query types if feature gate is enabled', async () => {
- render();
- openMenu(screen.getByLabelText('select query type'));
- await waitFor(() => expect(screen.getByText('Subscriptions')).toBeInTheDocument());
- });
-
- it('should not show the new query types if feature gate is disabled', async () => {
- grafanaRuntime.config.featureToggles.azTemplateVars = false;
- render();
- openMenu(screen.getByLabelText('select query type'));
- await waitFor(() => expect(screen.queryByText('Subscriptions')).not.toBeInTheDocument());
- });
it('should run the query if requesting subscriptions', async () => {
const onChange = jest.fn();
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.tsx
index 9626f13685f..049377dd479 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.tsx
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/VariableEditor/VariableEditor.tsx
@@ -3,11 +3,10 @@ import React, { useEffect, useState } from 'react';
import { useEffectOnce } from 'react-use';
import { SelectableValue } from '@grafana/data';
-import { config } from '@grafana/runtime';
import { Alert, InlineField, Select } from '@grafana/ui';
import DataSource from '../../datasource';
-import { migrateStringQueriesToObjectQueries } from '../../grafanaTemplateVariableFns';
+import { migrateQuery } from '../../grafanaTemplateVariableFns';
import { AzureMonitorOption, AzureMonitorQuery, AzureQueryType } from '../../types';
import useLastError from '../../utils/useLastError';
import LogsQueryEditor from '../LogsQueryEditor';
@@ -26,16 +25,20 @@ const removeOption: SelectableValue = { label: '-', value: '' };
const VariableEditor = (props: Props) => {
const { query, onChange, datasource } = props;
const AZURE_QUERY_VARIABLE_TYPE_OPTIONS = [
- { label: 'Grafana Query Function', value: AzureQueryType.GrafanaTemplateVariableFn },
+ { label: 'Subscriptions', value: AzureQueryType.SubscriptionsQuery },
+ { label: 'Resource Groups', value: AzureQueryType.ResourceGroupsQuery },
+ { label: 'Namespaces', value: AzureQueryType.NamespacesQuery },
+ { label: 'Resource Names', value: AzureQueryType.ResourceNamesQuery },
+ { label: 'Metric Names', value: AzureQueryType.MetricNamesQuery },
+ { label: 'Workspaces', value: AzureQueryType.WorkspacesQuery },
{ label: 'Logs', value: AzureQueryType.LogAnalytics },
];
- if (config.featureToggles.azTemplateVars) {
- AZURE_QUERY_VARIABLE_TYPE_OPTIONS.push({ label: 'Subscriptions', value: AzureQueryType.SubscriptionsQuery });
- AZURE_QUERY_VARIABLE_TYPE_OPTIONS.push({ label: 'Resource Groups', value: AzureQueryType.ResourceGroupsQuery });
- AZURE_QUERY_VARIABLE_TYPE_OPTIONS.push({ label: 'Namespaces', value: AzureQueryType.NamespacesQuery });
- AZURE_QUERY_VARIABLE_TYPE_OPTIONS.push({ label: 'Resource Names', value: AzureQueryType.ResourceNamesQuery });
- AZURE_QUERY_VARIABLE_TYPE_OPTIONS.push({ label: 'Metric Names', value: AzureQueryType.MetricNamesQuery });
- AZURE_QUERY_VARIABLE_TYPE_OPTIONS.push({ label: 'Workspaces', value: AzureQueryType.WorkspacesQuery });
+ if (typeof props.query === 'object' && props.query.queryType === AzureQueryType.GrafanaTemplateVariableFn) {
+ // Add the option for the GrafanaTemplateVariableFn only if it's already in use
+ AZURE_QUERY_VARIABLE_TYPE_OPTIONS.push({
+ label: 'Grafana Query Function',
+ value: AzureQueryType.GrafanaTemplateVariableFn,
+ });
}
const [variableOptionGroup, setVariableOptionGroup] = useState<{ label: string; options: AzureMonitorOption[] }>({
label: 'Template Variables',
@@ -55,7 +58,7 @@ const VariableEditor = (props: Props) => {
const queryType = typeof query === 'string' ? '' : query.queryType;
useEffect(() => {
- migrateStringQueriesToObjectQueries(query, { datasource: datasource }).then((migratedQuery) => {
+ migrateQuery(query, { datasource: datasource }).then((migratedQuery) => {
onChange(migratedQuery);
});
}, [query, datasource, onChange]);
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts
index 3cdc108ba53..a443073162c 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts
@@ -1,3 +1,5 @@
+import { config } from '@grafana/runtime';
+
import { isGUIDish } from './components/ResourcePicker/utils';
import DataSource from './datasource';
import { AzureMonitorQuery, AzureQueryType } from './types';
@@ -253,6 +255,58 @@ const createLogAnalyticsTemplateVariableQuery = async (
};
};
+const migrateGrafanaTemplateVariableFn = (query: AzureMonitorQuery) => {
+ const { queryType, grafanaTemplateVariableFn } = query;
+ if (queryType !== AzureQueryType.GrafanaTemplateVariableFn || !grafanaTemplateVariableFn) {
+ return query;
+ }
+
+ const migratedQuery: AzureMonitorQuery = {
+ ...query,
+ };
+ if ('subscription' in grafanaTemplateVariableFn) {
+ migratedQuery.subscription = grafanaTemplateVariableFn.subscription;
+ }
+ if ('resourceGroup' in grafanaTemplateVariableFn) {
+ migratedQuery.resourceGroup = grafanaTemplateVariableFn.resourceGroup;
+ }
+ if ('metricDefinition' in grafanaTemplateVariableFn) {
+ migratedQuery.namespace = grafanaTemplateVariableFn.metricDefinition;
+ }
+ if ('metricNamespace' in grafanaTemplateVariableFn) {
+ migratedQuery.namespace = grafanaTemplateVariableFn.metricNamespace;
+ }
+ if ('resourceName' in grafanaTemplateVariableFn) {
+ migratedQuery.resource = grafanaTemplateVariableFn.resourceName;
+ }
+
+ switch (grafanaTemplateVariableFn.kind) {
+ case 'SubscriptionsQuery':
+ migratedQuery.queryType = AzureQueryType.SubscriptionsQuery;
+ break;
+ case 'ResourceGroupsQuery':
+ migratedQuery.queryType = AzureQueryType.ResourceGroupsQuery;
+ break;
+ case 'MetricDefinitionsQuery':
+ migratedQuery.queryType = AzureQueryType.NamespacesQuery;
+ break;
+ case 'ResourceNamesQuery':
+ migratedQuery.queryType = AzureQueryType.ResourceNamesQuery;
+ break;
+ case 'MetricNamespaceQuery':
+ migratedQuery.queryType = AzureQueryType.NamespacesQuery;
+ break;
+ case 'MetricNamesQuery':
+ migratedQuery.queryType = AzureQueryType.MetricNamesQuery;
+ break;
+ case 'WorkspacesQuery':
+ migratedQuery.queryType = AzureQueryType.WorkspacesQuery;
+ break;
+ }
+
+ return migratedQuery;
+};
+
export const migrateStringQueriesToObjectQueries = async (
rawQuery: string | AzureMonitorQuery,
options: { datasource: DataSource }
@@ -266,3 +320,19 @@ export const migrateStringQueriesToObjectQueries = async (
? createGrafanaTemplateVariableQuery(rawQuery, options.datasource)
: createLogAnalyticsTemplateVariableQuery(rawQuery, options.datasource);
};
+
+export const migrateQuery = async (
+ rawQuery: string | AzureMonitorQuery,
+ options: { datasource: DataSource }
+): Promise => {
+ let query = await migrateStringQueriesToObjectQueries(rawQuery, options);
+
+ if (
+ !config.featureToggles.azLegacyTemplateVariables &&
+ query.queryType === AzureQueryType.GrafanaTemplateVariableFn
+ ) {
+ query = migrateGrafanaTemplateVariableFn(query);
+ }
+
+ return query;
+};
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts
index f3e1df0554c..d478ea5d893 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts
@@ -1,5 +1,5 @@
import createMockDatasource from './__mocks__/datasource';
-import { migrateStringQueriesToObjectQueries } from './grafanaTemplateVariableFns';
+import { migrateQuery, migrateStringQueriesToObjectQueries } from './grafanaTemplateVariableFns';
import { AzureMonitorQuery, AzureQueryType } from './types';
describe('migrateStringQueriesToObjectQueries', () => {
@@ -239,3 +239,273 @@ describe('migrateStringQueriesToObjectQueries', () => {
});
});
});
+
+describe('migrateStringQueriesToObjectQueries', () => {
+ const expectedMigrations: Array<{ input: AzureMonitorQuery; output: AzureMonitorQuery }> = [
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: { kind: 'SubscriptionsQuery', rawQuery: 'Subscriptions()' },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.SubscriptionsQuery,
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'ResourceGroupsQuery',
+ rawQuery: 'ResourceGroups()',
+ subscription: 'defaultSubscriptionId',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.ResourceGroupsQuery,
+ subscription: 'defaultSubscriptionId',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'ResourceGroupsQuery',
+ rawQuery: 'ResourceGroups(subId)',
+ subscription: 'subId',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.ResourceGroupsQuery,
+ subscription: 'subId',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'MetricDefinitionsQuery',
+ rawQuery: 'Namespaces(rg)',
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.NamespacesQuery,
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'MetricDefinitionsQuery',
+ rawQuery: 'Namespaces(subId, rg)',
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.NamespacesQuery,
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'ResourceNamesQuery',
+ rawQuery: 'ResourceNames(rg, md)',
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ metricDefinition: 'md',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.ResourceNamesQuery,
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ namespace: 'md',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'ResourceNamesQuery',
+ rawQuery: 'ResourceNames(subId, rg, md)',
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ metricDefinition: 'md',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.ResourceNamesQuery,
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ namespace: 'md',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'MetricNamespaceQuery',
+ rawQuery: 'MetricNamespace(rg, md, rn)',
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ metricDefinition: 'md',
+ resourceName: 'rn',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.NamespacesQuery,
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ namespace: 'md',
+ resource: 'rn',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'MetricNamespaceQuery',
+ rawQuery: 'MetricNamespace(subId, rg, md, rn)',
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ metricDefinition: 'md',
+ resourceName: 'rn',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.NamespacesQuery,
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ namespace: 'md',
+ resource: 'rn',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'MetricNamesQuery',
+ rawQuery: 'MetricNames(rg, md, rn, mn)',
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ metricDefinition: 'md',
+ resourceName: 'rn',
+ metricNamespace: 'mn',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.MetricNamesQuery,
+ subscription: 'defaultSubscriptionId',
+ resourceGroup: 'rg',
+ namespace: 'mn',
+ resource: 'rn',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'MetricNamesQuery',
+ rawQuery: 'MetricNames(subId, rg, md, rn, mn)',
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ metricDefinition: 'md',
+ resourceName: 'rn',
+ metricNamespace: 'mn',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.MetricNamesQuery,
+ subscription: 'subId',
+ resourceGroup: 'rg',
+ namespace: 'mn',
+ resource: 'rn',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'WorkspacesQuery',
+ rawQuery: 'workspaces()',
+ subscription: 'defaultSubscriptionId',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.WorkspacesQuery,
+ subscription: 'defaultSubscriptionId',
+ },
+ },
+ {
+ input: {
+ refId: 'A',
+ queryType: AzureQueryType.GrafanaTemplateVariableFn,
+ grafanaTemplateVariableFn: {
+ kind: 'WorkspacesQuery',
+ rawQuery: 'workspaces(subId)',
+ subscription: 'subId',
+ },
+ subscription: 'defaultSubscriptionId',
+ },
+ output: {
+ refId: 'A',
+ queryType: AzureQueryType.WorkspacesQuery,
+ subscription: 'subId',
+ },
+ },
+ ];
+ it('successfully converts all old variable functions into formatted predefined queries', async () => {
+ return expectedMigrations.map(async ({ input, output }) => {
+ const datasource = createMockDatasource({
+ azureMonitorDatasource: {
+ defaultSubscriptionId: 'defaultSubscriptionId',
+ },
+ });
+ const actual = await migrateQuery(input, { datasource });
+ expect(actual).toMatchObject(output);
+ });
+ });
+});
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.test.ts
index 2fc9c36f002..339bde53363 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.test.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.test.ts
@@ -389,7 +389,7 @@ describe('VariableSupport', () => {
azureMonitorDatasource: {
defaultSubscriptionId: 'defaultSubscriptionId',
},
- getMetricDefinitions: jest.fn((sub: string, rg: string) => {
+ getMetricNamespaces: jest.fn((sub: string, rg: string) => {
if (sub === 'subscriptionId' && rg === 'resourceGroup') {
return Promise.resolve(expectedResults);
}
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.ts
index 0315cda03db..19375c755ac 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/variables.ts
@@ -11,7 +11,7 @@ import { getTemplateSrv } from '@grafana/runtime';
import VariableEditor from './components/VariableEditor/VariableEditor';
import DataSource from './datasource';
-import { migrateStringQueriesToObjectQueries } from './grafanaTemplateVariableFns';
+import { migrateQuery } from './grafanaTemplateVariableFns';
import { AzureMonitorQuery, AzureQueryType } from './types';
import { GrafanaTemplateVariableQuery } from './types/templateVariables';
import messageFromError from './utils/messageFromError';
@@ -27,7 +27,7 @@ export class VariableSupport extends CustomVariableSupport): Observable {
const promisedResults = async () => {
- const queryObj = await migrateStringQueriesToObjectQueries(request.targets[0], { datasource: this.datasource });
+ const queryObj = await migrateQuery(request.targets[0], { datasource: this.datasource });
try {
switch (queryObj.queryType) {
@@ -101,6 +101,7 @@ export class VariableSupport extends CustomVariableSupport | null {
if (query.kind === 'SubscriptionsQuery') {
return this.datasource.getSubscriptions();