[ML] Fix runtime field validations not supporting special script types (#122469)

* Fix validations not handling extra things like params or lang

* Add translations

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Quynh Nguyen 2022-01-18 12:19:33 -06:00 committed by GitHub
parent 7a70f857f3
commit f8d932f70a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 77 additions and 39 deletions

View file

@ -14,11 +14,12 @@ export function isRuntimeField(arg: unknown): arg is estypes.MappingRuntimeField
return (
((isPopulatedObject(arg, ['type']) && Object.keys(arg).length === 1) ||
(isPopulatedObject(arg, ['type', 'script']) &&
Object.keys(arg).length === 2 &&
// Can be a string
(typeof arg.script === 'string' ||
(isPopulatedObject(arg.script, ['source']) &&
Object.keys(arg.script).length === 1 &&
typeof arg.script.source === 'string')))) &&
// Can be InlineScript
(isPopulatedObject(arg.script, ['source']) && typeof arg.script.source === 'string') ||
// Can be StoredScriptId
(isPopulatedObject(arg.script, ['id']) && typeof arg.script.id === 'string')))) &&
RUNTIME_FIELD_TYPES.includes(arg.type as RuntimeType)
);
}

View file

@ -6,6 +6,7 @@
*/
import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';
import { isRuntimeField } from './utils/runtime_field_utils';
export const analyzeFileQuerySchema = schema.object({
@ -48,7 +49,9 @@ export const runtimeMappingsSchema = schema.object(
unknowns: 'allow',
validate: (v: object) => {
if (Object.values(v).some((o) => !isRuntimeField(o))) {
return 'Invalid runtime field';
return i18n.translate('xpack.fileUpload.invalidRuntimeFieldMessage', {
defaultMessage: 'Invalid runtime field',
});
}
},
}

View file

@ -15,11 +15,12 @@ export function isRuntimeField(arg: unknown): arg is estypes.MappingRuntimeField
return (
((isPopulatedObject(arg, ['type']) && Object.keys(arg).length === 1) ||
(isPopulatedObject(arg, ['type', 'script']) &&
Object.keys(arg).length === 2 &&
// Can be a string
(typeof arg.script === 'string' ||
(isPopulatedObject(arg.script, ['source']) &&
Object.keys(arg.script).length === 1 &&
typeof arg.script.source === 'string')))) &&
// Can be InlineScript
(isPopulatedObject(arg.script, ['source']) && typeof arg.script.source === 'string') ||
// Can be StoredScriptId
(isPopulatedObject(arg.script, ['id']) && typeof arg.script.id === 'string')))) &&
RUNTIME_FIELD_TYPES.includes(arg.type as RuntimeType)
);
}

View file

@ -30,7 +30,9 @@ describe('ML runtime field utils', () => {
expect(isRuntimeField({ type: 'keyword' })).toBe(true);
});
it('allows objects with both type and script attributes', () => {
expect(isRuntimeField({ type: 'keyword', script: 'some script' })).toBe(true);
expect(
isRuntimeField({ type: 'keyword', script: 'some script', format: 'some format' })
).toBe(true);
});
});
@ -90,6 +92,19 @@ describe('ML runtime field utils', () => {
isRuntimeMappings({
fieldName1: { type: 'keyword' },
fieldName2: { type: 'keyword', script: 'some script as script' },
fieldName3: {
type: 'keyword',
script: {
source: 'source script',
},
},
fieldName4: {
type: 'keyword',
script: {
source: 'source script',
params: {},
},
},
})
).toBe(true);
expect(
@ -97,6 +112,28 @@ describe('ML runtime field utils', () => {
fieldName: { type: 'long', script: { source: 'some script as source' } },
})
).toBe(true);
expect(
isRuntimeMappings({
fieldName: {
type: 'long',
script: {
source: 'source script',
params: {},
lang: 'lang',
},
},
})
).toBe(true);
expect(
isRuntimeMappings({
fieldName: {
type: 'long',
script: {
id: 'a script id',
},
},
})
).toBe(true);
});
});
});

View file

@ -7,7 +7,6 @@
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { isPopulatedObject } from './object_utils';
import { RUNTIME_FIELD_TYPES } from '../../../../../src/plugins/data/common';
import type { RuntimeMappings } from '../types/fields';
type RuntimeType = typeof RUNTIME_FIELD_TYPES[number];
@ -15,15 +14,16 @@ export function isRuntimeField(arg: unknown): arg is estypes.MappingRuntimeField
return (
((isPopulatedObject(arg, ['type']) && Object.keys(arg).length === 1) ||
(isPopulatedObject(arg, ['type', 'script']) &&
Object.keys(arg).length === 2 &&
// Can be a string
(typeof arg.script === 'string' ||
(isPopulatedObject(arg.script, ['source']) &&
Object.keys(arg.script).length === 1 &&
typeof arg.script.source === 'string')))) &&
// Can be InlineScript
(isPopulatedObject(arg.script, ['source']) && typeof arg.script.source === 'string') ||
// Can be StoredScriptId
(isPopulatedObject(arg.script, ['id']) && typeof arg.script.id === 'string')))) &&
RUNTIME_FIELD_TYPES.includes(arg.type as RuntimeType)
);
}
export function isRuntimeMappings(arg: unknown): arg is RuntimeMappings {
export function isRuntimeMappings(arg: unknown): arg is estypes.MappingRuntimeFields {
return isPopulatedObject(arg) && Object.values(arg).every((d) => isRuntimeField(d));
}

View file

@ -6,6 +6,7 @@
*/
import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';
import { isRuntimeField } from '../../../common/util/runtime_field_utils';
export const runtimeMappingsSchema = schema.object(
@ -14,7 +15,9 @@ export const runtimeMappingsSchema = schema.object(
unknowns: 'allow',
validate: (v: object) => {
if (Object.values(v).some((o) => !isRuntimeField(o))) {
return 'Invalid runtime field';
return i18n.translate('xpack.ml.invalidRuntimeFieldMessage', {
defaultMessage: 'Invalid runtime field',
});
}
},
}

View file

@ -6,8 +6,9 @@
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';
import { TRANSFORM_STATE } from '../constants';
import { isRuntimeField } from '../shared_imports';
export const transformIdsSchema = schema.arrayOf(
schema.object({
@ -57,26 +58,17 @@ export interface CommonResponseStatusSchema {
}
export const runtimeMappingsSchema = schema.maybe(
schema.recordOf(
schema.string(),
schema.object({
type: schema.oneOf([
schema.literal('keyword'),
schema.literal('long'),
schema.literal('double'),
schema.literal('date'),
schema.literal('ip'),
schema.literal('boolean'),
schema.literal('geo_point'),
]),
script: schema.maybe(
schema.oneOf([
schema.string(),
schema.object({
source: schema.string(),
}),
])
),
})
schema.object(
{},
{
unknowns: 'allow',
validate: (v: object) => {
if (Object.values(v).some((o) => !isRuntimeField(o))) {
return i18n.translate('xpack.transform.invalidRuntimeFieldMessage', {
defaultMessage: 'Invalid runtime field',
});
}
},
}
)
);

View file

@ -11,6 +11,7 @@ export {
isPopulatedObject,
isRuntimeMappings,
patternValidator,
isRuntimeField,
} from '../../ml/common';
export { RUNTIME_FIELD_TYPES } from '../../../../src/plugins/data/common';