CloudWatch: Set accountId to undefined if not monitoring account (#108112)

This commit is contained in:
Ida Štambuk
2025-07-16 10:19:40 +02:00
committed by GitHub
parent 3cda233468
commit 4cc4c6c666
2 changed files with 53 additions and 4 deletions
@@ -1,4 +1,4 @@
import { render, screen } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import selectEvent from 'react-select-event';
import { CustomVariableModel, DataSourceInstanceSettings } from '@grafana/data';
@@ -7,7 +7,7 @@ import * as ui from '@grafana/ui';
import { CloudWatchDatasource } from '../../../datasource';
import { setupMockedTemplateService } from '../../../mocks/CloudWatchDataSource';
import { initialVariableModelState } from '../../../mocks/CloudWatchVariables';
import { CloudWatchJsonData, MetricEditorMode, MetricQueryType } from '../../../types';
import { CloudWatchJsonData, CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../../../types';
import { MetricsQueryEditor, Props } from './MetricsQueryEditor';
@@ -18,7 +18,16 @@ jest.mock('@grafana/ui', () => ({
},
}));
const setup = () => {
jest.mock('@grafana/runtime', () => ({
...jest.requireActual<typeof import('@grafana/runtime')>('@grafana/runtime'),
config: {
featureToggles: {
cloudWatchCrossAccountQuerying: true,
},
},
}));
const setup = (customQuery?: Partial<CloudWatchMetricsQuery>, isMonitoringAccount?: boolean) => {
const instanceSettings = {
jsonData: { defaultRegion: 'us-east-1' },
} as DataSourceInstanceSettings<CloudWatchJsonData>;
@@ -47,7 +56,7 @@ const setup = () => {
datasource.resources.getMetrics = jest.fn().mockResolvedValue([]);
datasource.resources.getRegions = jest.fn().mockResolvedValue([]);
datasource.resources.getDimensionKeys = jest.fn().mockResolvedValue([]);
datasource.resources.isMonitoringAccount = jest.fn().mockResolvedValue(false);
datasource.resources.isMonitoringAccount = jest.fn().mockResolvedValue(isMonitoringAccount ?? false);
const props: Props = {
query: {
@@ -65,6 +74,7 @@ const setup = () => {
matchExact: true,
metricQueryType: MetricQueryType.Search,
metricEditorMode: MetricEditorMode.Builder,
...customQuery,
},
extraHeaderElementLeft: () => {},
extraHeaderElementRight: () => {},
@@ -121,4 +131,31 @@ describe('QueryEditor', () => {
expect(screen.queryByText('Alias')).toBeNull();
expect(screen.getByText("Period: ${PROP('Period')} InstanceId: ${PROP('Dim.InstanceId')}"));
});
it('should clear accountId field when datasource connects to a non-monitoring account', async () => {
const props = setup({ accountId: '123456789' });
render(<MetricsQueryEditor {...props} />);
expect(props.datasource.resources.isMonitoringAccount).toHaveBeenCalledWith('us-east-1');
await waitFor(async () => {
expect(props.onChange).toHaveBeenCalledWith({
...props.query,
accountId: undefined,
});
});
});
it('should keep accountId field when datasource connects to a monitoring account', async () => {
const props = setup({ accountId: '123456789' }, true);
render(<MetricsQueryEditor {...props} />);
expect(props.datasource.resources.isMonitoringAccount).toHaveBeenCalledWith('us-east-1');
await waitFor(async () => {
expect(props.onChange).not.toHaveBeenCalledWith({
...props.query,
accountId: undefined,
});
});
});
});
@@ -3,6 +3,7 @@ import * as React from 'react';
import { QueryEditorProps, SelectableValue } from '@grafana/data';
import { EditorField, EditorRow, InlineSelect } from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { ConfirmModal, Input, RadioButtonGroup, Space } from '@grafana/ui';
import { CloudWatchDatasource } from '../../../datasource';
@@ -59,6 +60,17 @@ export const MetricsQueryEditor = (props: Props) => {
[setShowConfirm, onChange, codeEditorIsDirty, query]
);
const updateAccounIdOnMount = () => {
if (config.featureToggles.cloudWatchCrossAccountQuerying && query.accountId) {
datasource.resources.isMonitoringAccount(query.region).then((isMonitoring) => {
if (!isMonitoring && query.accountId) {
onChange({ ...query, accountId: undefined });
}
});
}
};
useEffect(updateAccounIdOnMount, [datasource, onChange, query]);
useEffect(() => {
extraHeaderElementLeft?.(
<InlineSelect