InfluxDB: Fix sending retention policy with InfluxQL queries (#63820)

* Send retention policy if that is specified

* Define the type

* Update default retention policy name

* Update unit tests

* fix unit tests

* fix unit tests again

* Load retention policies at first

* Fix tests

* Fix Editor tests

* Remove unused code

* A simpler approach

* Even simpler

* Even simpler
This commit is contained in:
ismail simsek
2023-03-28 18:20:15 +02:00
committed by GitHub
parent 273e05a9a2
commit 0aee7338ad
11 changed files with 113 additions and 73 deletions

View File

@@ -11,6 +11,7 @@ import { Editor } from './Editor';
jest.mock('../../influxQLMetadataQuery', () => {
return {
__esModule: true,
getAllPolicies: jest.fn().mockReturnValueOnce(Promise.resolve(['default', 'autogen'])),
getFieldKeysForMeasurement: jest
.fn()
.mockReturnValueOnce(Promise.resolve(['free', 'total']))

View File

@@ -1,4 +1,4 @@
import { render } from '@testing-library/react';
import { act, render } from '@testing-library/react';
import React from 'react';
import InfluxDatasource from '../../datasource';
@@ -35,24 +35,27 @@ jest.mock('./Seg', () => {
};
});
function assertEditor(query: InfluxQuery, textContent: string) {
async function assertEditor(query: InfluxQuery, textContent: string) {
const onChange = jest.fn();
const onRunQuery = jest.fn();
const datasource: InfluxDatasource = {
metricFindQuery: () => Promise.resolve([]),
} as unknown as InfluxDatasource;
const { container } = render(
<Editor query={query} datasource={datasource} onChange={onChange} onRunQuery={onRunQuery} />
);
expect(container.textContent).toBe(textContent);
await act(async () => {
const { container } = await render(
<Editor query={query} datasource={datasource} onChange={onChange} onRunQuery={onRunQuery} />
);
expect(container.textContent).toBe(textContent);
});
}
describe('InfluxDB InfluxQL Visual Editor', () => {
it('should handle minimal query', () => {
it('should handle minimal query', async () => {
const query: InfluxQuery = {
refId: 'A',
policy: 'default',
};
assertEditor(
await assertEditor(
query,
'FROM[default][select measurement]WHERE[+]' +
'SELECT[field]([value])[mean]()[+]' +
@@ -62,13 +65,14 @@ describe('InfluxDB InfluxQL Visual Editor', () => {
'FORMAT AS[time_series]ALIAS[Naming pattern]'
);
});
it('should have the alias-field hidden when format-as-table', () => {
it('should have the alias-field hidden when format-as-table', async () => {
const query: InfluxQuery = {
refId: 'A',
alias: 'test-alias',
resultFormat: 'table',
policy: 'default',
};
assertEditor(
await assertEditor(
query,
'FROM[default][select measurement]WHERE[+]' +
'SELECT[field]([value])[mean]()[+]' +
@@ -78,7 +82,7 @@ describe('InfluxDB InfluxQL Visual Editor', () => {
'FORMAT AS[table]'
);
});
it('should handle complex query', () => {
it('should handle complex query', async () => {
const query: InfluxQuery = {
refId: 'A',
policy: 'default',
@@ -147,7 +151,7 @@ describe('InfluxDB InfluxQL Visual Editor', () => {
tz: 'UTC',
alias: 'all i as',
};
assertEditor(
await assertEditor(
query,
'FROM[default][cpu]WHERE[cpu][=][cpu1][AND][cpu][<][cpu3][+]' +
'SELECT[field]([usage_idle])[mean]()[+]' +

View File

@@ -1,5 +1,6 @@
import { css } from '@emotion/css';
import React, { useMemo } from 'react';
import { useAsync } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
@@ -76,6 +77,9 @@ export const Editor = (props: Props): JSX.Element => {
const { datasource } = props;
const { measurement, policy } = query;
const policyData = useAsync(() => getAllPolicies(datasource), [datasource]);
const retentionPolicies = !!policyData.error ? [] : policyData.value ?? [];
const allTagKeys = useMemo(async () => {
const tagKeys = (await getTagKeysForMeasurementAndTags(measurement, policy, [], datasource)).map(
(tag) => `${tag}::tag`
@@ -143,7 +147,7 @@ export const Editor = (props: Props): JSX.Element => {
<div>
<SegmentSection label="FROM" fill={true}>
<FromSection
policy={policy}
policy={policy ?? retentionPolicies[0]}
measurement={measurement}
getPolicyOptions={() => getAllPolicies(datasource)}
getMeasurementOptions={(filter) =>

View File

@@ -3,8 +3,6 @@ import React from 'react';
import { Seg } from './Seg';
import { toSelectableValue } from './toSelectableValue';
const DEFAULT_POLICY = 'default';
// we use the value "default" as a magic-value, it means
// we use the default retention-policy.
// unfortunately, IF the user has a retention-policy named "default",
@@ -33,12 +31,7 @@ export const FromSection = ({
}: Props): JSX.Element => {
const handlePolicyLoadOptions = async () => {
const allPolicies = await getPolicyOptions();
// if `default` does not exist in the list of policies, we add it
const allPoliciesWithDefault = allPolicies.some((p) => p === 'default')
? allPolicies
: [DEFAULT_POLICY, ...allPolicies];
return allPoliciesWithDefault.map(toSelectableValue);
return allPolicies.map(toSelectableValue);
};
const handleMeasurementLoadOptions = async (filter: string) => {
@@ -50,7 +43,7 @@ export const FromSection = ({
<>
<Seg
allowCustomValue
value={policy ?? 'using default policy'}
value={policy ?? ''}
loadOptions={handlePolicyLoadOptions}
onChange={(v) => {
onChange(v.value, measurement);