[Alerting] Improve comparator types of es_query && index_threshold rules (#129190)

* [Alerting] improve comparator types

* [Discover] fix unit tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Dmitry Tomashevich 2022-04-07 14:59:31 +05:00 committed by GitHub
parent ac50a30eb6
commit 3522a7fdc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 29 deletions

View file

@ -190,9 +190,15 @@ describe('alertType Params validate()', () => {
it('fails for invalid thresholdComparator', async () => {
params.thresholdComparator = '[invalid-comparator]';
expect(onValidate()).toThrowErrorMatchingInlineSnapshot(
`"[thresholdComparator]: invalid thresholdComparator specified: [invalid-comparator]"`
);
expect(onValidate()).toThrowErrorMatchingInlineSnapshot(`
"[thresholdComparator]: types that failed validation:
- [thresholdComparator.0]: expected value to equal [>]
- [thresholdComparator.1]: expected value to equal [<]
- [thresholdComparator.2]: expected value to equal [>=]
- [thresholdComparator.3]: expected value to equal [<=]
- [thresholdComparator.4]: expected value to equal [between]
- [thresholdComparator.5]: expected value to equal [notBetween]"
`);
});
it('fails for invalid threshold length', async () => {

View file

@ -6,11 +6,12 @@
*/
import { i18n } from '@kbn/i18n';
import { schema, Type, TypeOf } from '@kbn/config-schema';
import { schema, TypeOf } from '@kbn/config-schema';
import { validateTimeWindowUnits } from '../../../../triggers_actions_ui/server';
import { RuleTypeState } from '../../../../alerting/server';
import { Comparator } from '../../../common/comparator_types';
import { ComparatorFnNames } from '../lib';
import { getComparatorSchemaType } from '../lib/comparator';
export const ES_QUERY_MAX_HITS_PER_EXECUTION = 10000;
@ -25,7 +26,7 @@ const EsQueryAlertParamsSchemaProperties = {
timeWindowSize: schema.number({ min: 1 }),
timeWindowUnit: schema.string({ validate: validateTimeWindowUnits }),
threshold: schema.arrayOf(schema.number(), { minSize: 1, maxSize: 2 }),
thresholdComparator: schema.string({ validate: validateComparator }) as Type<Comparator>,
thresholdComparator: getComparatorSchemaType(validateComparator),
searchType: schema.nullable(schema.literal('searchSource')),
// searchSource alert param only
searchConfiguration: schema.conditional(
@ -94,8 +95,8 @@ function validateParams(anyParams: unknown): string | undefined {
}
}
function validateComparator(comparator: string): string | undefined {
if (ComparatorFnNames.has(comparator as Comparator)) return;
function validateComparator(comparator: Comparator): string | undefined {
if (ComparatorFnNames.has(comparator)) return;
return i18n.translate('xpack.stackAlerts.esQuery.invalidComparatorErrorMessage', {
defaultMessage: 'invalid thresholdComparator specified: {comparator}',

View file

@ -46,9 +46,15 @@ describe('alertType Params validate()', () => {
it('fails for invalid comparator', async () => {
params.thresholdComparator = '[invalid-comparator]';
expect(onValidate()).toThrowErrorMatchingInlineSnapshot(
`"[thresholdComparator]: invalid thresholdComparator specified: [invalid-comparator]"`
);
expect(onValidate()).toThrowErrorMatchingInlineSnapshot(`
"[thresholdComparator]: types that failed validation:
- [thresholdComparator.0]: expected value to equal [>]
- [thresholdComparator.1]: expected value to equal [<]
- [thresholdComparator.2]: expected value to equal [>=]
- [thresholdComparator.3]: expected value to equal [<=]
- [thresholdComparator.4]: expected value to equal [between]
- [thresholdComparator.5]: expected value to equal [notBetween]"
`);
});
it('fails for invalid threshold length', async () => {
@ -121,24 +127,24 @@ export function runTests(schema: ObjectType, defaultTypeParams: Record<string, u
params.index = 42;
expect(onValidate()).toThrowErrorMatchingInlineSnapshot(`
"[index]: types that failed validation:
- [index.0]: expected value of type [string] but got [number]
- [index.1]: expected value of type [array] but got [number]"
`);
"[index]: types that failed validation:
- [index.0]: expected value of type [string] but got [number]
- [index.1]: expected value of type [array] but got [number]"
`);
params.index = '';
expect(onValidate()).toThrowErrorMatchingInlineSnapshot(`
"[index]: types that failed validation:
- [index.0]: value has length [0] but it must have a minimum length of [1].
- [index.1]: could not parse array value from json input"
`);
"[index]: types that failed validation:
- [index.0]: value has length [0] but it must have a minimum length of [1].
- [index.1]: could not parse array value from json input"
`);
params.index = ['', 'a'];
expect(onValidate()).toThrowErrorMatchingInlineSnapshot(`
"[index]: types that failed validation:
- [index.0]: expected value of type [string] but got [Array]
- [index.1.0]: value has length [0] but it must have a minimum length of [1]."
`);
"[index]: types that failed validation:
- [index.0]: expected value of type [string] but got [Array]
- [index.1.0]: value has length [0] but it must have a minimum length of [1]."
`);
});
it('fails for invalid timeField', async () => {

View file

@ -6,13 +6,14 @@
*/
import { i18n } from '@kbn/i18n';
import { schema, Type, TypeOf } from '@kbn/config-schema';
import { schema, TypeOf } from '@kbn/config-schema';
import {
CoreQueryParamsSchemaProperties,
validateCoreQueryBody,
} from '../../../../triggers_actions_ui/server';
import { ComparatorFnNames } from '../lib';
import { Comparator } from '../../../common/comparator_types';
import { getComparatorSchemaType } from '../lib/comparator';
// alert type parameters
@ -22,14 +23,12 @@ export const ParamsSchema = schema.object(
{
...CoreQueryParamsSchemaProperties,
// the comparison function to use to determine if the threshold as been met
thresholdComparator: schema.string({ validate: validateComparator }) as Type<Comparator>,
thresholdComparator: getComparatorSchemaType(validateComparator),
// the values to use as the threshold; `between` and `notBetween` require
// two values, the others require one.
threshold: schema.arrayOf(schema.number(), { minSize: 1, maxSize: 2 }),
},
{
validate: validateParams,
}
{ validate: validateParams }
);
const betweenComparators = new Set(['between', 'notBetween']);
@ -53,8 +52,8 @@ function validateParams(anyParams: unknown): string | undefined {
}
}
function validateComparator(comparator: string): string | undefined {
if (ComparatorFnNames.has(comparator as Comparator)) return;
function validateComparator(comparator: Comparator): string | undefined {
if (ComparatorFnNames.has(comparator)) return;
return i18n.translate('xpack.stackAlerts.indexThreshold.invalidComparatorErrorMessage', {
defaultMessage: 'invalid thresholdComparator specified: {comparator}',

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { schema } from '@kbn/config-schema';
import { Comparator } from '../../../common/comparator_types';
export type ComparatorFn = (value: number, threshold: number[]) => boolean;
@ -33,6 +34,19 @@ export const ComparatorFns = new Map<Comparator, ComparatorFn>([
],
]);
export const getComparatorSchemaType = (validate: (comparator: Comparator) => string | void) =>
schema.oneOf(
[
schema.literal(Comparator.GT),
schema.literal(Comparator.LT),
schema.literal(Comparator.GT_OR_EQ),
schema.literal(Comparator.LT_OR_EQ),
schema.literal(Comparator.BETWEEN),
schema.literal(Comparator.NOT_BETWEEN),
],
{ validate }
);
export const ComparatorFnNames = new Set(ComparatorFns.keys());
export function getHumanReadableComparator(comparator: Comparator) {