mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Cloudwatch : Fixed reseting metric name when changing namespace in Metric Query (#44612)
* Added logic to reset metric name when changing namespace in Metric Query * Added tests for reseting or not metricName onChange namespace * Added tests for reseting or not metricName onChange namespace * Removed comment * Cleaned up tests * Refactored namespace to be updated in utils * Removed unecessary overrides for query and onQueryChange * Renamed tests + used some instead of find
This commit is contained in:
parent
fd14112dbd
commit
33a7269b4f
@ -0,0 +1,137 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { selectOptionInTest } from '@grafana/ui';
|
||||||
|
import { act, render, screen } from '@testing-library/react';
|
||||||
|
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType, SQLExpression } from '../../types';
|
||||||
|
import { setupMockedDataSource } from '../../__mocks__/CloudWatchDataSource';
|
||||||
|
import { QueryEditorExpressionType, QueryEditorPropertyType } from '../../expressions';
|
||||||
|
import SQLBuilderSelectRow from './SQLBuilderSelectRow';
|
||||||
|
|
||||||
|
const { datasource } = setupMockedDataSource();
|
||||||
|
|
||||||
|
const makeSQLQuery = (sql?: SQLExpression): CloudWatchMetricsQuery => ({
|
||||||
|
queryMode: 'Metrics',
|
||||||
|
refId: '',
|
||||||
|
id: '',
|
||||||
|
region: 'us-east-1',
|
||||||
|
namespace: 'ec2',
|
||||||
|
dimensions: { somekey: 'somevalue' },
|
||||||
|
metricQueryType: MetricQueryType.Query,
|
||||||
|
metricEditorMode: MetricEditorMode.Builder,
|
||||||
|
sql: sql,
|
||||||
|
});
|
||||||
|
|
||||||
|
const query = makeSQLQuery({
|
||||||
|
select: {
|
||||||
|
type: QueryEditorExpressionType.Function,
|
||||||
|
name: 'AVERAGE',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
type: QueryEditorExpressionType.FunctionParameter,
|
||||||
|
name: 'm1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
from: {
|
||||||
|
type: QueryEditorExpressionType.Property,
|
||||||
|
property: {
|
||||||
|
type: QueryEditorPropertyType.String,
|
||||||
|
name: 'n1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onQueryChange = jest.fn();
|
||||||
|
const baseProps = {
|
||||||
|
query,
|
||||||
|
datasource,
|
||||||
|
onQueryChange,
|
||||||
|
};
|
||||||
|
|
||||||
|
const namespaces = [
|
||||||
|
{ value: 'n1', label: 'n1', text: 'n1' },
|
||||||
|
{ value: 'n2', label: 'n2', text: 'n2' },
|
||||||
|
];
|
||||||
|
const metrics = [
|
||||||
|
{ value: 'm1', label: 'm1', text: 'm1' },
|
||||||
|
{ value: 'm2', label: 'm2', text: 'm2' },
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('Cloudwatch SQLBuilderSelectRow', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
datasource.getNamespaces = jest.fn().mockResolvedValue(namespaces);
|
||||||
|
datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
||||||
|
datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
||||||
|
datasource.getDimensionValues = jest.fn().mockResolvedValue([]);
|
||||||
|
onQueryChange.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not reset metricName when selecting a namespace if metric exist in new namespace', async () => {
|
||||||
|
datasource.getMetrics = jest.fn().mockResolvedValue(metrics);
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
render(<SQLBuilderSelectRow {...baseProps} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('n1')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('m1')).toBeInTheDocument();
|
||||||
|
const namespaceSelect = screen.getByLabelText('Namespace');
|
||||||
|
await selectOptionInTest(namespaceSelect, 'n2');
|
||||||
|
|
||||||
|
const expectedQuery = makeSQLQuery({
|
||||||
|
select: {
|
||||||
|
type: QueryEditorExpressionType.Function,
|
||||||
|
name: 'AVERAGE',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
type: QueryEditorExpressionType.FunctionParameter,
|
||||||
|
name: 'm1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
from: {
|
||||||
|
type: QueryEditorExpressionType.Property,
|
||||||
|
property: {
|
||||||
|
type: QueryEditorPropertyType.String,
|
||||||
|
name: 'n2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(onQueryChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(onQueryChange.mock.calls).toEqual([[{ ...expectedQuery, namespace: 'n2' }]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should reset metricName when selecting a namespace if metric does not exist in new namespace', async () => {
|
||||||
|
datasource.getMetrics = jest.fn().mockImplementation((namespace: string, region: string) => {
|
||||||
|
let mockMetrics =
|
||||||
|
namespace === 'n1' && region === baseProps.query.region
|
||||||
|
? metrics
|
||||||
|
: [{ value: 'newNamespaceMetric', label: 'newNamespaceMetric', text: 'newNamespaceMetric' }];
|
||||||
|
return Promise.resolve(mockMetrics);
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
render(<SQLBuilderSelectRow {...baseProps} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('n1')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('m1')).toBeInTheDocument();
|
||||||
|
const namespaceSelect = screen.getByLabelText('Namespace');
|
||||||
|
await selectOptionInTest(namespaceSelect, 'n2');
|
||||||
|
|
||||||
|
const expectedQuery = makeSQLQuery({
|
||||||
|
select: {
|
||||||
|
type: QueryEditorExpressionType.Function,
|
||||||
|
name: 'AVERAGE',
|
||||||
|
},
|
||||||
|
from: {
|
||||||
|
type: QueryEditorExpressionType.Property,
|
||||||
|
property: {
|
||||||
|
type: QueryEditorPropertyType.String,
|
||||||
|
name: 'n2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(onQueryChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(onQueryChange.mock.calls).toEqual([[{ ...expectedQuery, namespace: 'n2' }]]);
|
||||||
|
});
|
||||||
|
});
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { toOption } from '@grafana/data';
|
import { SelectableValue, toOption } from '@grafana/data';
|
||||||
import { EditorField, EditorFieldGroup } from '@grafana/experimental';
|
import { EditorField, EditorFieldGroup } from '@grafana/experimental';
|
||||||
import { Select, Switch } from '@grafana/ui';
|
import { Select, Switch } from '@grafana/ui';
|
||||||
import { STATISTICS } from '../../cloudwatch-sql/language';
|
import { STATISTICS } from '../../cloudwatch-sql/language';
|
||||||
@ -12,6 +12,7 @@ import {
|
|||||||
getNamespaceFromExpression,
|
getNamespaceFromExpression,
|
||||||
getSchemaLabelKeys as getSchemaLabels,
|
getSchemaLabelKeys as getSchemaLabels,
|
||||||
isUsingWithSchema,
|
isUsingWithSchema,
|
||||||
|
removeMetricName,
|
||||||
setAggregation,
|
setAggregation,
|
||||||
setMetricName,
|
setMetricName,
|
||||||
setNamespace,
|
setNamespace,
|
||||||
@ -52,16 +53,32 @@ const SQLBuilderSelectRow: React.FC<SQLBuilderSelectRowProps> = ({ datasource, q
|
|||||||
[unusedDimensionKeys, schemaLabels]
|
[unusedDimensionKeys, schemaLabels]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onNamespaceChange = async (query: CloudWatchMetricsQuery) => {
|
||||||
|
const validatedQuery = await validateMetricName(query);
|
||||||
|
onQueryChange(validatedQuery);
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateMetricName = async (query: CloudWatchMetricsQuery) => {
|
||||||
|
let { region, sql } = query;
|
||||||
|
await datasource.getMetrics(query.namespace, region).then((result: Array<SelectableValue<string>>) => {
|
||||||
|
if (!result.some((metric) => metric.value === metricName)) {
|
||||||
|
sql = removeMetricName(query).sql;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { ...query, sql };
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EditorFieldGroup>
|
<EditorFieldGroup>
|
||||||
<EditorField label="Namespace" width={16}>
|
<EditorField label="Namespace" width={16}>
|
||||||
<Select
|
<Select
|
||||||
|
aria-label="Namespace"
|
||||||
value={namespace ? toOption(namespace) : null}
|
value={namespace ? toOption(namespace) : null}
|
||||||
inputId={`${query.refId}-cloudwatch-sql-namespace`}
|
inputId={`${query.refId}-cloudwatch-sql-namespace`}
|
||||||
options={namespaceOptions}
|
options={namespaceOptions}
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
onChange={({ value }) => value && onQueryChange(setNamespace(query, value))}
|
onChange={({ value }) => value && onNamespaceChange(setNamespace(query, value))}
|
||||||
menuShouldPortal
|
menuShouldPortal
|
||||||
/>
|
/>
|
||||||
</EditorField>
|
</EditorField>
|
||||||
|
@ -146,6 +146,8 @@ export function setSql(query: CloudWatchMetricsQuery, sql: SQLExpression): Cloud
|
|||||||
|
|
||||||
export function setNamespace(query: CloudWatchMetricsQuery, namespace: string | undefined): CloudWatchMetricsQuery {
|
export function setNamespace(query: CloudWatchMetricsQuery, namespace: string | undefined): CloudWatchMetricsQuery {
|
||||||
const sql = query.sql ?? {};
|
const sql = query.sql ?? {};
|
||||||
|
//updating `namespace` props for CloudWatchMetricsQuery
|
||||||
|
query.namespace = namespace ? namespace : '';
|
||||||
|
|
||||||
if (namespace === undefined) {
|
if (namespace === undefined) {
|
||||||
return setSql(query, {
|
return setSql(query, {
|
||||||
@ -230,6 +232,13 @@ export function setMetricName(query: CloudWatchMetricsQuery, metricName: string)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function removeMetricName(query: CloudWatchMetricsQuery): CloudWatchMetricsQuery {
|
||||||
|
const queryWithNoParams = { ...query };
|
||||||
|
delete queryWithNoParams.sql?.select?.parameters;
|
||||||
|
|
||||||
|
return queryWithNoParams;
|
||||||
|
}
|
||||||
|
|
||||||
export function setAggregation(query: CloudWatchMetricsQuery, aggregation: string): CloudWatchMetricsQuery {
|
export function setAggregation(query: CloudWatchMetricsQuery, aggregation: string): CloudWatchMetricsQuery {
|
||||||
return setSql(query, {
|
return setSql(query, {
|
||||||
select: {
|
select: {
|
||||||
|
Loading…
Reference in New Issue
Block a user