Skip to content

Commit

Permalink
[ML] Improve runtime mappings validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
walterra committed Mar 1, 2021
1 parent 18d936b commit 3c4b5c7
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { EuiCodeEditor } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { StepDefineFormHook } from '../step_define';
import { isRuntimeMappings } from '../step_define/common/types';

export const AdvancedRuntimeMappingsEditor: FC<StepDefineFormHook['runtimeMappingsEditor']> = memo(
({
Expand Down Expand Up @@ -43,8 +44,8 @@ export const AdvancedRuntimeMappingsEditor: FC<StepDefineFormHook['runtimeMappin
// Try to parse the string passed on from the editor.
// If parsing fails, the "Apply"-Button will be disabled
try {
JSON.parse(convertToJson(d));
setRuntimeMappingsEditorApplyButtonEnabled(true);
const parsedJson = JSON.parse(convertToJson(d));
setRuntimeMappingsEditorApplyButtonEnabled(isRuntimeMappings(parsedJson));
} catch (e) {
setRuntimeMappingsEditorApplyButtonEnabled(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { getDefaultAggregationConfig } from './get_default_aggregation_config';
import { getDefaultGroupByConfig } from './get_default_group_by_config';
import type { Field, StepDefineExposedState } from './types';
import { isPopulatedObject } from '../../../../../common/utils/object_utils';
import { isRuntimeMappings } from './types';

const illegalEsAggNameChars = /[[\]>]/g;

Expand Down Expand Up @@ -77,7 +77,7 @@ export function getPivotDropdownOptions(

// Support for runtime_mappings that are defined by queries
let runtimeFields: Field[] = [];
if (isPopulatedObject(runtimeMappings)) {
if (isRuntimeMappings(runtimeMappings)) {
runtimeFields = Object.keys(runtimeMappings).map((fieldName) => {
const field = runtimeMappings[fieldName];
return { name: fieldName, type: getKibanaFieldTypeFromEsType(field.type) };
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { isRuntimeField, isRuntimeMappings } from './types';

describe('Transform: step_define type guards', () => {
it('isRuntimeField()', () => {
expect(isRuntimeField(1)).toBe(false);
expect(isRuntimeField(null)).toBe(false);
expect(isRuntimeField([])).toBe(false);
expect(isRuntimeField({})).toBe(false);
expect(isRuntimeField({ someAttribute: 'someValue' })).toBe(false);
expect(isRuntimeField({ type: 'wrong-type' })).toBe(false);
expect(isRuntimeField({ type: 'keyword', someAttribute: 'some value' })).toBe(false);

expect(isRuntimeField({ type: 'keyword' })).toBe(true);
expect(isRuntimeField({ type: 'keyword', script: 'some script' })).toBe(true);
});

it('isRuntimeMappings()', () => {
expect(isRuntimeMappings(1)).toBe(false);
expect(isRuntimeMappings(null)).toBe(false);
expect(isRuntimeMappings([])).toBe(false);
expect(isRuntimeMappings({})).toBe(false);
expect(isRuntimeMappings({ someAttribute: 'someValue' })).toBe(false);
expect(isRuntimeMappings({ fieldName1: { type: 'keyword' }, fieldName2: 'someValue' })).toBe(
false
);
expect(
isRuntimeMappings({
fieldName1: { type: 'keyword' },
fieldName2: { type: 'keyword', someAttribute: 'some value' },
})
).toBe(false);

expect(isRuntimeMappings({ fieldName: { type: 'keyword' } })).toBe(true);
expect(
isRuntimeMappings({ fieldName1: { type: 'keyword' }, fieldName2: { type: 'keyword' } })
).toBe(true);
expect(
isRuntimeMappings({
fieldName1: { type: 'keyword' },
fieldName2: { type: 'keyword', script: 'some script' },
})
).toBe(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
} from '../../../../../../../common/types/transform';
import { LatestFunctionConfig } from '../../../../../../../common/api_schemas/transforms';

import { isPopulatedObject } from '../../../../../common/utils/object_utils';

export interface ErrorMessage {
query: string;
message: string;
Expand Down Expand Up @@ -70,10 +72,25 @@ export interface StepDefineExposedState {
isRuntimeMappingsEditorEnabled: boolean;
}

export function isRuntimeField(arg: any): arg is RuntimeField {
return (
isPopulatedObject(arg) &&
((Object.keys(arg).length === 1 && arg.hasOwnProperty('type')) ||
(Object.keys(arg).length === 2 &&
arg.hasOwnProperty('type') &&
arg.hasOwnProperty('script'))) &&
RUNTIME_FIELD_TYPES.includes(arg.type)
);
}

export function isRuntimeMappings(arg: any): arg is RuntimeMappings {
return isPopulatedObject(arg) && Object.values(arg).every((d) => isRuntimeField(d));
}

export function isPivotPartialRequest(arg: any): arg is { pivot: PivotConfigDefinition } {
return typeof arg === 'object' && arg.hasOwnProperty('pivot');
return isPopulatedObject(arg) && arg.hasOwnProperty('pivot');
}

export function isLatestPartialRequest(arg: any): arg is { latest: LatestFunctionConfig } {
return typeof arg === 'object' && arg.hasOwnProperty('latest');
return isPopulatedObject(arg) && arg.hasOwnProperty('latest');
}

0 comments on commit 3c4b5c7

Please sign in to comment.