mirror of
https://github.com/grafana/grafana.git
synced 2025-09-28 00:23:57 +08:00
CloudWatch: Remove error message when using multi-valued template vars in region field (#45886)
* don't show error message when using multi-valued template variables in region field * add unit tests * remove commented code
This commit is contained in:
@ -1,11 +1,12 @@
|
|||||||
import { dateTime } from '@grafana/data';
|
import { dateTime } from '@grafana/data';
|
||||||
import { setBackendSrv } from '@grafana/runtime';
|
import { setBackendSrv } from '@grafana/runtime';
|
||||||
import { TemplateSrvMock } from '../../../../features/templating/template_srv.mock';
|
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||||
import { initialCustomVariableModelState } from 'app/features/variables/custom/reducer';
|
import { initialCustomVariableModelState } from 'app/features/variables/custom/reducer';
|
||||||
import { CustomVariableModel } from 'app/features/variables/types';
|
import { CustomVariableModel } from 'app/features/variables/types';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
|
import { TemplateSrvMock } from '../../../../features/templating/template_srv.mock';
|
||||||
import { CloudWatchDatasource } from '../datasource';
|
import { CloudWatchDatasource } from '../datasource';
|
||||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
|
||||||
|
|
||||||
export function setupMockedDataSource({ data = [], variables }: { data?: any; variables?: any } = {}) {
|
export function setupMockedDataSource({ data = [], variables }: { data?: any; variables?: any } = {}) {
|
||||||
let templateService = new TemplateSrvMock({
|
let templateService = new TemplateSrvMock({
|
||||||
@ -16,6 +17,8 @@ export function setupMockedDataSource({ data = [], variables }: { data?: any; va
|
|||||||
if (variables) {
|
if (variables) {
|
||||||
templateService = new TemplateSrv();
|
templateService = new TemplateSrv();
|
||||||
templateService.init(variables);
|
templateService.init(variables);
|
||||||
|
templateService.getVariables = jest.fn().mockReturnValue(variables);
|
||||||
|
templateService.getVariableName = (name: string) => name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const datasource = new CloudWatchDatasource(
|
const datasource = new CloudWatchDatasource(
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import React from 'react';
|
|
||||||
import { pick } from 'lodash';
|
|
||||||
|
|
||||||
import { ExploreMode, SelectableValue } from '@grafana/data';
|
import { ExploreMode, SelectableValue } from '@grafana/data';
|
||||||
import { EditorHeader, InlineSelect } from '@grafana/experimental';
|
import { EditorHeader, InlineSelect } from '@grafana/experimental';
|
||||||
|
import { pick } from 'lodash';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
import { CloudWatchDatasource } from '../datasource';
|
import { CloudWatchDatasource } from '../datasource';
|
||||||
import { CloudWatchQuery, CloudWatchQueryMode } from '../types';
|
|
||||||
import { useRegions } from '../hooks';
|
import { useRegions } from '../hooks';
|
||||||
|
import { CloudWatchQuery, CloudWatchQueryMode } from '../types';
|
||||||
import MetricsQueryHeader from './MetricsQueryHeader';
|
import MetricsQueryHeader from './MetricsQueryHeader';
|
||||||
|
|
||||||
interface QueryHeaderProps {
|
interface QueryHeaderProps {
|
||||||
@ -59,7 +58,7 @@ const QueryHeader: React.FC<QueryHeaderProps> = ({
|
|||||||
<EditorHeader>
|
<EditorHeader>
|
||||||
<InlineSelect
|
<InlineSelect
|
||||||
label="Region"
|
label="Region"
|
||||||
value={regions.find((v) => v.value === region)}
|
value={region}
|
||||||
placeholder="Select region"
|
placeholder="Select region"
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
onChange={({ value: region }) => region && onRegion({ value: region })}
|
onChange={({ value: region }) => region && onRegion({ value: region })}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { lastValueFrom, of } from 'rxjs';
|
|
||||||
import { setDataSourceSrv } from '@grafana/runtime';
|
|
||||||
import { ArrayVector, DataFrame, dataFrameToJSON, dateTime, Field, MutableDataFrame } from '@grafana/data';
|
import { ArrayVector, DataFrame, dataFrameToJSON, dateTime, Field, MutableDataFrame } from '@grafana/data';
|
||||||
|
import { setDataSourceSrv } from '@grafana/runtime';
|
||||||
|
import { lastValueFrom, of } from 'rxjs';
|
||||||
import { toArray } from 'rxjs/operators';
|
import { toArray } from 'rxjs/operators';
|
||||||
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType, CloudWatchLogsQueryStatus } from './types';
|
|
||||||
import {
|
import {
|
||||||
setupMockedDataSource,
|
|
||||||
namespaceVariable,
|
|
||||||
metricVariable,
|
|
||||||
labelsVariable,
|
labelsVariable,
|
||||||
limitVariable,
|
limitVariable,
|
||||||
|
metricVariable,
|
||||||
|
namespaceVariable,
|
||||||
|
setupMockedDataSource,
|
||||||
} from './__mocks__/CloudWatchDataSource';
|
} from './__mocks__/CloudWatchDataSource';
|
||||||
import { CloudWatchDatasource } from './datasource';
|
import { CloudWatchDatasource } from './datasource';
|
||||||
|
import { CloudWatchLogsQueryStatus, CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from './types';
|
||||||
|
|
||||||
describe('datasource', () => {
|
describe('datasource', () => {
|
||||||
describe('query', () => {
|
describe('query', () => {
|
||||||
@ -91,6 +91,57 @@ describe('datasource', () => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('debouncedCustomAlert', () => {
|
||||||
|
const debouncedAlert = jest.fn();
|
||||||
|
beforeEach(() => {
|
||||||
|
const { datasource } = setupMockedDataSource({
|
||||||
|
variables: [
|
||||||
|
{ ...namespaceVariable, multi: true },
|
||||||
|
{ ...metricVariable, multi: true },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
datasource.debouncedCustomAlert = debouncedAlert;
|
||||||
|
datasource.performTimeSeriesQuery = jest.fn().mockResolvedValue([]);
|
||||||
|
datasource.query({
|
||||||
|
targets: [
|
||||||
|
{
|
||||||
|
queryMode: 'Metrics',
|
||||||
|
id: '',
|
||||||
|
region: 'us-east-2',
|
||||||
|
namespace: namespaceVariable.id,
|
||||||
|
metricName: metricVariable.id,
|
||||||
|
period: '',
|
||||||
|
alias: '',
|
||||||
|
dimensions: {},
|
||||||
|
matchExact: true,
|
||||||
|
statistic: '',
|
||||||
|
refId: '',
|
||||||
|
expression: 'x * 2',
|
||||||
|
metricQueryType: MetricQueryType.Search,
|
||||||
|
metricEditorMode: MetricEditorMode.Code,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as any);
|
||||||
|
});
|
||||||
|
it('should show debounced alert for namespace and metric name', async () => {
|
||||||
|
expect(debouncedAlert).toHaveBeenCalledWith(
|
||||||
|
'CloudWatch templating error',
|
||||||
|
'Multi template variables are not supported for namespace'
|
||||||
|
);
|
||||||
|
expect(debouncedAlert).toHaveBeenCalledWith(
|
||||||
|
'CloudWatch templating error',
|
||||||
|
'Multi template variables are not supported for metric name'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show debounced alert for region', async () => {
|
||||||
|
expect(debouncedAlert).not.toHaveBeenCalledWith(
|
||||||
|
'CloudWatch templating error',
|
||||||
|
'Multi template variables are not supported for region'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('filterMetricQuery', () => {
|
describe('filterMetricQuery', () => {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
import { cloneDeep, find, findLast, isEmpty, isString, set } from 'lodash';
|
|
||||||
import { from, lastValueFrom, merge, Observable, of, throwError, zip } from 'rxjs';
|
|
||||||
import { catchError, concatMap, finalize, map, mergeMap, repeat, scan, share, takeWhile, tap } from 'rxjs/operators';
|
|
||||||
import { DataSourceWithBackend, FetchError, getBackendSrv, toDataQueryResponse } from '@grafana/runtime';
|
|
||||||
import { RowContextOptions } from '@grafana/ui/src/components/Logs/LogRowContextProvider';
|
|
||||||
import {
|
import {
|
||||||
DataFrame,
|
DataFrame,
|
||||||
DataQueryError,
|
DataQueryError,
|
||||||
@ -22,44 +16,50 @@ import {
|
|||||||
TimeRange,
|
TimeRange,
|
||||||
toLegacyResponseData,
|
toLegacyResponseData,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
import { DataSourceWithBackend, FetchError, getBackendSrv, toDataQueryResponse } from '@grafana/runtime';
|
||||||
|
import { toTestingStatus } from '@grafana/runtime/src/utils/queryResponse';
|
||||||
|
import { RowContextOptions } from '@grafana/ui/src/components/Logs/LogRowContextProvider';
|
||||||
import { notifyApp } from 'app/core/actions';
|
import { notifyApp } from 'app/core/actions';
|
||||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||||
import { AppNotificationTimeout } from 'app/types';
|
|
||||||
import { store } from 'app/store/store';
|
|
||||||
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
|
|
||||||
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
|
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
|
||||||
|
import { VariableWithMultiSupport } from 'app/features/variables/types';
|
||||||
|
import { store } from 'app/store/store';
|
||||||
|
import { AppNotificationTimeout } from 'app/types';
|
||||||
|
import { cloneDeep, find, findLast, isEmpty, isString, set } from 'lodash';
|
||||||
|
import React from 'react';
|
||||||
|
import { from, lastValueFrom, merge, Observable, of, throwError, zip } from 'rxjs';
|
||||||
|
import { catchError, concatMap, finalize, map, mergeMap, repeat, scan, share, takeWhile, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { SQLCompletionItemProvider } from './cloudwatch-sql/completion/CompletionItemProvider';
|
||||||
import { ThrottlingErrorMessage } from './components/ThrottlingErrorMessage';
|
import { ThrottlingErrorMessage } from './components/ThrottlingErrorMessage';
|
||||||
|
import { CloudWatchLanguageProvider } from './language_provider';
|
||||||
import memoizedDebounce from './memoizedDebounce';
|
import memoizedDebounce from './memoizedDebounce';
|
||||||
|
import { MetricMathCompletionItemProvider } from './metric-math/completion/CompletionItemProvider';
|
||||||
import {
|
import {
|
||||||
MetricEditorMode,
|
|
||||||
CloudWatchJsonData,
|
CloudWatchJsonData,
|
||||||
CloudWatchLogsQuery,
|
CloudWatchLogsQuery,
|
||||||
CloudWatchLogsQueryStatus,
|
CloudWatchLogsQueryStatus,
|
||||||
|
CloudWatchLogsRequest,
|
||||||
CloudWatchMetricsQuery,
|
CloudWatchMetricsQuery,
|
||||||
CloudWatchQuery,
|
CloudWatchQuery,
|
||||||
DescribeLogGroupsRequest,
|
DescribeLogGroupsRequest,
|
||||||
|
Dimensions,
|
||||||
GetLogEventsRequest,
|
GetLogEventsRequest,
|
||||||
GetLogGroupFieldsRequest,
|
GetLogGroupFieldsRequest,
|
||||||
GetLogGroupFieldsResponse,
|
GetLogGroupFieldsResponse,
|
||||||
isCloudWatchLogsQuery,
|
isCloudWatchLogsQuery,
|
||||||
LogAction,
|
LogAction,
|
||||||
MetricQueryType,
|
MetricEditorMode,
|
||||||
MetricQuery,
|
MetricQuery,
|
||||||
|
MetricQueryType,
|
||||||
MetricRequest,
|
MetricRequest,
|
||||||
StartQueryRequest,
|
StartQueryRequest,
|
||||||
TSDBResponse,
|
TSDBResponse,
|
||||||
Dimensions,
|
|
||||||
CloudWatchLogsRequest,
|
|
||||||
} from './types';
|
} from './types';
|
||||||
import { CloudWatchLanguageProvider } from './language_provider';
|
|
||||||
import { VariableWithMultiSupport } from 'app/features/variables/types';
|
|
||||||
import { increasingInterval } from './utils/rxjs/increasingInterval';
|
|
||||||
import { toTestingStatus } from '@grafana/runtime/src/utils/queryResponse';
|
|
||||||
import { addDataLinksToLogsResponse } from './utils/datalinks';
|
import { addDataLinksToLogsResponse } from './utils/datalinks';
|
||||||
import { runWithRetry } from './utils/logsRetry';
|
import { runWithRetry } from './utils/logsRetry';
|
||||||
import { SQLCompletionItemProvider } from './cloudwatch-sql/completion/CompletionItemProvider';
|
import { increasingInterval } from './utils/rxjs/increasingInterval';
|
||||||
import { MetricMathCompletionItemProvider } from './metric-math/completion/CompletionItemProvider';
|
|
||||||
|
|
||||||
const DS_QUERY_ENDPOINT = '/api/ds/query';
|
const DS_QUERY_ENDPOINT = '/api/ds/query';
|
||||||
|
|
||||||
@ -268,7 +268,7 @@ export class CloudWatchDatasource
|
|||||||
const validMetricsQueries = metricQueries
|
const validMetricsQueries = metricQueries
|
||||||
.filter(this.filterMetricQuery)
|
.filter(this.filterMetricQuery)
|
||||||
.map((item: CloudWatchMetricsQuery): MetricQuery => {
|
.map((item: CloudWatchMetricsQuery): MetricQuery => {
|
||||||
item.region = this.replace(this.getActualRegion(item.region), options.scopedVars, true, 'region');
|
item.region = this.templateSrv.replace(this.getActualRegion(item.region), options.scopedVars);
|
||||||
item.namespace = this.replace(item.namespace, options.scopedVars, true, 'namespace');
|
item.namespace = this.replace(item.namespace, options.scopedVars, true, 'namespace');
|
||||||
item.metricName = this.replace(item.metricName, options.scopedVars, true, 'metric name');
|
item.metricName = this.replace(item.metricName, options.scopedVars, true, 'metric name');
|
||||||
item.dimensions = this.convertDimensionFormat(item.dimensions ?? {}, options.scopedVars);
|
item.dimensions = this.convertDimensionFormat(item.dimensions ?? {}, options.scopedVars);
|
||||||
|
Reference in New Issue
Block a user