From a4bf5e407db68ec4664d2645cba5454632b29293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81bastien=20Loix?= Date: Tue, 7 Jul 2020 17:34:57 +0200 Subject: [PATCH] Add data stream field in logistics step --- .../common/lib/template_serialization.ts | 11 +- .../common/types/templates.ts | 10 +- .../template_form/steps/step_logistics.tsx | 149 ++++++++++++------ .../template_form/template_form_schemas.tsx | 28 +++- .../routes/api/templates/validate_schemas.ts | 1 + 5 files changed, 140 insertions(+), 59 deletions(-) diff --git a/x-pack/plugins/index_management/common/lib/template_serialization.ts b/x-pack/plugins/index_management/common/lib/template_serialization.ts index 5c55860bda81..a799a4214c6c 100644 --- a/x-pack/plugins/index_management/common/lib/template_serialization.ts +++ b/x-pack/plugins/index_management/common/lib/template_serialization.ts @@ -13,13 +13,22 @@ import { const hasEntries = (data: object = {}) => Object.entries(data).length > 0; export function serializeTemplate(templateDeserialized: TemplateDeserialized): TemplateSerialized { - const { version, priority, indexPatterns, template, composedOf, _meta } = templateDeserialized; + const { + version, + priority, + indexPatterns, + template, + composedOf, + dataStream, + _meta, + } = templateDeserialized; return { version, priority, template, index_patterns: indexPatterns, + data_stream: dataStream, composed_of: composedOf, _meta, }; diff --git a/x-pack/plugins/index_management/common/types/templates.ts b/x-pack/plugins/index_management/common/types/templates.ts index fdcac40ca596..b7e336dc6f58 100644 --- a/x-pack/plugins/index_management/common/types/templates.ts +++ b/x-pack/plugins/index_management/common/types/templates.ts @@ -38,15 +38,15 @@ export interface TemplateDeserialized { aliases?: Aliases; mappings?: Mappings; }; - composedOf?: string[]; // Used on composable index template + composedOf?: string[]; // Composable template only version?: number; - priority?: number; - order?: number; // Used on legacy index template + priority?: number; // Composable template only + order?: number; // Legacy template only ilmPolicy?: { name: string; }; - _meta?: { [key: string]: any }; - dataStream?: { timestamp_field: string }; + _meta?: { [key: string]: any }; // Composable template only + dataStream?: { timestamp_field: string }; // Composable template only _kbnMeta: { isManaged: boolean; isCloudManaged: boolean; diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx index 00940c39c8f8..4edc8ba026ab 100644 --- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx +++ b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx @@ -4,7 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import React, { useEffect } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiButtonEmpty, EuiSpacer } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiButtonEmpty, + EuiSpacer, + EuiLink, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -25,56 +32,82 @@ import { schemas, nameConfig, nameConfigWithoutValidations } from '../template_f const UseField = getUseField({ component: Field }); const FormRow = getFormRow({ titleTag: 'h3' }); -const fieldsMeta = { - name: { - title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameTitle', { - defaultMessage: 'Name', - }), - description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameDescription', { - defaultMessage: 'A unique identifier for this template.', - }), - testSubject: 'nameField', - }, - indexPatterns: { - title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.indexPatternsTitle', { - defaultMessage: 'Index patterns', - }), - description: i18n.translate( - 'xpack.idxMgmt.templateForm.stepLogistics.indexPatternsDescription', - { - defaultMessage: 'The index patterns to apply to the template.', - } - ), - testSubject: 'indexPatternsField', - }, - order: { - title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderTitle', { - defaultMessage: 'Merge order', - }), - description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderDescription', { - defaultMessage: 'The merge order when multiple templates match an index.', - }), - testSubject: 'orderField', - }, - priority: { - title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityTitle', { - defaultMessage: 'Priority', - }), - description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityDescription', { - defaultMessage: 'Only the highest priority template will be applied.', - }), - testSubject: 'priorityField', - }, - version: { - title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionTitle', { - defaultMessage: 'Version', - }), - description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionDescription', { - defaultMessage: 'A number that identifies the template to external management systems.', - }), - testSubject: 'versionField', - }, -}; +function getFieldsMeta(esDocsBase: string) { + return { + name: { + title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameTitle', { + defaultMessage: 'Name', + }), + description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameDescription', { + defaultMessage: 'A unique identifier for this template.', + }), + testSubject: 'nameField', + }, + indexPatterns: { + title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.indexPatternsTitle', { + defaultMessage: 'Index patterns', + }), + description: i18n.translate( + 'xpack.idxMgmt.templateForm.stepLogistics.indexPatternsDescription', + { + defaultMessage: 'The index patterns to apply to the template.', + } + ), + testSubject: 'indexPatternsField', + }, + dataStream: { + title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.dataStreamTitle', { + defaultMessage: 'Data stream', + }), + description: ( + +
+ + {i18n.translate('xpack.idxMgmt.mappingsEditor.dynamicMappingDocumentionLink', { + defaultMessage: 'Learn more about data streams.', + })} + + + ), + }} + /> + ), + testSubject: 'dataStreamField', + }, + order: { + title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderTitle', { + defaultMessage: 'Merge order', + }), + description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderDescription', { + defaultMessage: 'The merge order when multiple templates match an index.', + }), + testSubject: 'orderField', + }, + priority: { + title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityTitle', { + defaultMessage: 'Priority', + }), + description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityDescription', { + defaultMessage: 'Only the highest priority template will be applied.', + }), + testSubject: 'priorityField', + }, + version: { + title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionTitle', { + defaultMessage: 'Version', + }), + description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionDescription', { + defaultMessage: 'A number that identifies the template to external management systems.', + }), + testSubject: 'versionField', + }, + }; +} interface LogisticsForm { [key: string]: any; @@ -144,7 +177,9 @@ export const StepLogistics: React.FunctionComponent = React.memo( return subscription.unsubscribe; }, [onChange]); // eslint-disable-line react-hooks/exhaustive-deps - const { name, indexPatterns, order, priority, version } = fieldsMeta; + const { name, indexPatterns, dataStream, order, priority, version } = getFieldsMeta( + documentationService.getEsDocsBase() + ); return ( <> @@ -207,6 +242,16 @@ export const StepLogistics: React.FunctionComponent = React.memo( /> + {/* Create data stream */} + {isLegacy !== true && ( + + + + )} + {/* Order */} {isLegacy && ( diff --git a/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx b/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx index b42ee4804c5c..d8c3ad8c259f 100644 --- a/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx +++ b/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx @@ -128,6 +128,32 @@ export const schemas: Record = { }, ], }, + dataStream: { + type: FIELD_TYPES.TOGGLE, + label: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.datastreamLabel', { + defaultMessage: 'Create data stream', + }), + defaultValue: false, + serializer: (value) => { + if (value === true) { + return { + timestamp_field: '@timestamp', + }; + } + }, + deserializer: (value) => { + if (typeof value === 'boolean') { + return value; + } + + /** + * For now, it is enough to have a "data_stream" declared on the index template + * to assume that the template creates a data stream. In the future, this condition + * might change + */ + return value !== undefined; + }, + }, order: { type: FIELD_TYPES.NUMBER, label: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.fieldOrderLabel', { @@ -193,7 +219,7 @@ export const schemas: Record = { label: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.addMetadataLabel', { defaultMessage: 'Add metadata', }), - } as FieldConfig, + }, }, }, }; diff --git a/x-pack/plugins/index_management/server/routes/api/templates/validate_schemas.ts b/x-pack/plugins/index_management/server/routes/api/templates/validate_schemas.ts index c905f92d7054..963947790782 100644 --- a/x-pack/plugins/index_management/server/routes/api/templates/validate_schemas.ts +++ b/x-pack/plugins/index_management/server/routes/api/templates/validate_schemas.ts @@ -20,6 +20,7 @@ export const templateSchema = schema.object({ }) ), composedOf: schema.maybe(schema.arrayOf(schema.string())), + dataStream: schema.maybe(schema.object({}, { unknowns: 'allow' })), _meta: schema.maybe(schema.object({}, { unknowns: 'allow' })), ilmPolicy: schema.maybe( schema.object({