diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.test.tsx
new file mode 100644
index 00000000000..7fbd74de615
--- /dev/null
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.test.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import MetricNamespaceField from './MetricNamespaceField';
+import createMockQuery from '../../__mocks__/query';
+import createMockDatasource from '../../__mocks__/datasource';
+import { AzureMonitorOption } from '../../types';
+
+const props = {
+ metricNamespaces: [],
+ query: createMockQuery(),
+ datasource: createMockDatasource(),
+ variableOptionGroup: { label: 'Templates', options: [] },
+ onQueryChange: jest.fn(),
+ setError: jest.fn(),
+};
+
+describe('Azure Monitor QueryEditor', () => {
+ it('should render the current value', async () => {
+ const metricNamespaces: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
+ const query = {
+ ...props.query,
+ azureMonitor: {
+ metricNamespace: 'foo',
+ },
+ };
+ render();
+ expect(screen.queryByText('foo')).toBeInTheDocument();
+ });
+
+ it('should render the current value even if it is not in the list of options', async () => {
+ const metricNamespaces: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
+ const query = {
+ ...props.query,
+ azureMonitor: {
+ metricNamespace: 'bar',
+ },
+ };
+ render();
+ expect(screen.queryByText('bar')).toBeInTheDocument();
+ expect(screen.queryByText('foo')).not.toBeInTheDocument();
+ });
+});
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx
index 99f2a365e8f..7d7992045c5 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx
@@ -29,6 +29,11 @@ const MetricNamespaceField: React.FC = ({
);
const options = useMemo(() => [...metricNamespaces, variableOptionGroup], [metricNamespaces, variableOptionGroup]);
+ const optionValues = metricNamespaces.map((m) => m.value).concat(variableOptionGroup.options.map((p) => p.value));
+ const value = query.azureMonitor?.metricNamespace;
+ if (value && !optionValues.includes(value)) {
+ options.push({ label: value, value });
+ }
return (
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.test.ts
index 22a9af6cabb..e47ff20776f 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.test.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.test.ts
@@ -5,6 +5,7 @@ import {
updateSubscriptions,
useAsyncState,
useMetricNames,
+ useMetricNamespaces,
useResourceGroups,
useResourceNames,
useResourceTypes,
@@ -93,7 +94,7 @@ interface TestScenario {
invalidQueryPartial: AzureMetricQuery;
templateVariableQueryPartial: AzureMetricQuery;
- expectedClearedQueryPartial: AzureMetricQuery;
+ expectedClearedQueryPartial?: AzureMetricQuery;
expectedOptions: AzureMonitorOption[];
}
@@ -253,6 +254,47 @@ describe('AzureMonitor: metrics dataHooks', () => {
metricName: undefined,
},
},
+
+ {
+ name: 'useMetricNamespaces',
+ hook: useMetricNamespaces,
+ emptyQueryPartial: {
+ resourceGroup: 'web-app-development',
+ metricDefinition: 'azure/vm',
+ resourceName: 'web-server',
+ metricNamespace: 'azure/vm',
+ },
+ validQueryPartial: {
+ resourceGroup: 'web-app-development',
+ metricDefinition: 'azure/vm',
+ resourceName: 'web-server',
+ metricNamespace: 'azure/vm',
+ },
+ invalidQueryPartial: {
+ resourceGroup: 'web-app-development',
+ metricDefinition: 'azure/vm',
+ resourceName: 'web-server',
+ metricNamespace: 'azure/vm',
+ metricName: 'invalid-metric',
+ },
+ templateVariableQueryPartial: {
+ resourceGroup: 'web-app-development',
+ metricDefinition: 'azure/vm',
+ resourceName: 'web-server',
+ metricNamespace: 'azure/vm',
+ metricName: '$variable',
+ },
+ expectedOptions: [
+ {
+ label: 'Compute Virtual Machine',
+ value: 'azure/vmc',
+ },
+ {
+ label: 'Database NS',
+ value: 'azure/dbns',
+ },
+ ],
+ },
];
let datasource: MockedObjectDeep;
@@ -284,8 +326,11 @@ describe('AzureMonitor: metrics dataHooks', () => {
datasource.getMetricNames = jest
.fn()
.mockResolvedValue([opt('Percentage CPU', 'percentage-cpu'), opt('Free memory', 'free-memory')]);
- });
+ datasource.getMetricNamespaces = jest
+ .fn()
+ .mockResolvedValue([opt('Compute Virtual Machine', 'azure/vmc'), opt('Database NS', 'azure/dbns')]);
+ });
describe.each(testTable)('scenario %#: $name', (scenario) => {
it('returns values', async () => {
const query = {
@@ -339,14 +384,18 @@ describe('AzureMonitor: metrics dataHooks', () => {
const { waitForNextUpdate } = renderHook(() => scenario.hook(query, datasource, onChange, setError));
await waitForNextUpdate(WAIT_OPTIONS);
- expect(onChange).toHaveBeenCalledWith({
- ...query,
- azureMonitor: {
- ...scenario.expectedClearedQueryPartial,
- dimensionFilters: [],
- timeGrain: '',
- },
- });
+ if (scenario.expectedClearedQueryPartial) {
+ expect(onChange).toHaveBeenCalledWith({
+ ...query,
+ azureMonitor: {
+ ...scenario.expectedClearedQueryPartial,
+ dimensionFilters: [],
+ timeGrain: '',
+ },
+ });
+ } else {
+ expect(onChange).not.toHaveBeenCalled();
+ }
});
});
});
diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.ts
index 0977360cec1..7a6d1c1458f 100644
--- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.ts
+++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/dataHooks.ts
@@ -193,8 +193,6 @@ export const useMetricNamespaces: DataHook = (query, datasource, onChange, setEr
// Do some cleanup of the query state if need be
if (!metricNamespace && options.length) {
onChange(setMetricNamespace(query, options[0].value));
- } else if (options[0] && isInvalidOption(metricNamespace, options, datasource.getVariables())) {
- onChange(setMetricNamespace(query, options[0].value));
}
return options;