From 4cc4c6c66692639fe24d06737ea038be79a4828e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ida=20=C5=A0tambuk?= Date: Wed, 16 Jul 2025 10:19:40 +0200 Subject: [PATCH] CloudWatch: Set accountId to undefined if not monitoring account (#108112) --- .../MetricsQueryEditor.test.tsx | 45 +++++++++++++++++-- .../MetricsQueryEditor/MetricsQueryEditor.tsx | 12 +++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx index bb87c2c6d19..ee9255a4fde 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx @@ -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('@grafana/runtime'), + config: { + featureToggles: { + cloudWatchCrossAccountQuerying: true, + }, + }, +})); + +const setup = (customQuery?: Partial, isMonitoringAccount?: boolean) => { const instanceSettings = { jsonData: { defaultRegion: 'us-east-1' }, } as DataSourceInstanceSettings; @@ -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(); + + 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(); + + expect(props.datasource.resources.isMonitoringAccount).toHaveBeenCalledWith('us-east-1'); + await waitFor(async () => { + expect(props.onChange).not.toHaveBeenCalledWith({ + ...props.query, + accountId: undefined, + }); + }); + }); }); diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx index 2740403e522..bbb7d1272b1 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx @@ -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?.(