diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx
index 6ba2454025beb..2897551a209b2 100644
--- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx
+++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx
@@ -71,6 +71,10 @@ describe('', () => {
const templateToEdit = fixtures.getTemplate({
name: 'index_template_without_mappings',
indexPatterns: ['indexPattern1'],
+ dataStream: {
+ hidden: true,
+ anyUnknownKey: 'should_be_kept',
+ },
});
beforeAll(() => {
@@ -85,7 +89,7 @@ describe('', () => {
testBed.component.update();
});
- it('allows you to add mappings', async () => {
+ test('allows you to add mappings', async () => {
const { actions, find } = testBed;
// Logistics
await actions.completeStepOne();
@@ -98,6 +102,47 @@ describe('', () => {
expect(find('fieldsListItem').length).toBe(1);
});
+
+ test('should keep data stream configuration', async () => {
+ const { actions } = testBed;
+ // Logistics
+ await actions.completeStepOne({
+ name: 'test',
+ indexPatterns: ['myPattern*'],
+ version: 1,
+ });
+ // Component templates
+ await actions.completeStepTwo();
+ // Index settings
+ await actions.completeStepThree();
+ // Mappings
+ await actions.completeStepFour();
+ // Aliases
+ await actions.completeStepFive();
+
+ await act(async () => {
+ actions.clickNextButton();
+ });
+
+ const latestRequest = server.requests[server.requests.length - 1];
+
+ const expected = {
+ name: 'test',
+ indexPatterns: ['myPattern*'],
+ dataStream: {
+ hidden: true,
+ anyUnknownKey: 'should_be_kept',
+ },
+ version: 1,
+ _kbnMeta: {
+ type: 'default',
+ isLegacy: false,
+ hasDatastream: true,
+ },
+ };
+
+ expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual(expected);
+ });
});
describe('with mappings', () => {
diff --git a/x-pack/plugins/index_management/common/types/templates.ts b/x-pack/plugins/index_management/common/types/templates.ts
index d1b51fe5b89bf..7b442b9dd2935 100644
--- a/x-pack/plugins/index_management/common/types/templates.ts
+++ b/x-pack/plugins/index_management/common/types/templates.ts
@@ -46,7 +46,11 @@ export interface TemplateDeserialized {
name: string;
};
_meta?: { [key: string]: any }; // Composable template only
- dataStream?: {}; // Composable template only
+ // Composable template only
+ dataStream?: {
+ hidden?: boolean;
+ [key: string]: any;
+ };
_kbnMeta: {
type: TemplateType;
hasDatastream: 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 89e857eec0bb3..bbc3656195470 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
@@ -55,7 +55,7 @@ function getFieldsMeta(esDocsBase: string) {
),
testSubject: 'indexPatternsField',
},
- dataStream: {
+ createDataStream: {
title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.dataStreamTitle', {
defaultMessage: 'Data stream',
}),
@@ -119,6 +119,7 @@ interface LogisticsForm {
interface LogisticsFormInternal extends LogisticsForm {
addMeta: boolean;
+ doCreateDataStream: boolean;
}
interface Props {
@@ -132,12 +133,16 @@ function formDeserializer(formData: LogisticsForm): LogisticsFormInternal {
return {
...formData,
addMeta: Boolean(formData._meta && Object.keys(formData._meta).length),
+ doCreateDataStream: Boolean(formData.dataStream),
};
}
-function formSerializer(formData: LogisticsFormInternal): LogisticsForm {
- const { addMeta, ...rest } = formData;
- return rest;
+function getformSerializer(initialTemplateData: LogisticsForm = {}) {
+ return (formData: LogisticsFormInternal): LogisticsForm => {
+ const { addMeta, doCreateDataStream, ...rest } = formData;
+ const dataStream = doCreateDataStream ? initialTemplateData.dataStream ?? {} : undefined;
+ return { ...rest, dataStream };
+ };
}
export const StepLogistics: React.FunctionComponent = React.memo(
@@ -146,7 +151,7 @@ export const StepLogistics: React.FunctionComponent = React.memo(
schema: schemas.logistics,
defaultValue,
options: { stripEmptyFields: false },
- serializer: formSerializer,
+ serializer: getformSerializer(defaultValue),
deserializer: formDeserializer,
});
const {
@@ -178,7 +183,7 @@ export const StepLogistics: React.FunctionComponent = React.memo(
});
}, [onChange, isFormValid, validate, getFormData]);
- const { name, indexPatterns, dataStream, order, priority, version } = getFieldsMeta(
+ const { name, indexPatterns, createDataStream, order, priority, version } = getFieldsMeta(
documentationService.getEsDocsBase()
);
@@ -245,10 +250,10 @@ export const StepLogistics: React.FunctionComponent = React.memo(
{/* Create data stream */}
{isLegacy !== true && (
-
+
)}
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 c85126f08685e..2bc146c118ba2 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
@@ -129,31 +129,12 @@ export const schemas: Record = {
},
],
},
- dataStream: {
+ doCreateDataStream: {
type: FIELD_TYPES.TOGGLE,
label: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.datastreamLabel', {
defaultMessage: 'Create data stream',
}),
defaultValue: false,
- serializer: (value) => {
- if (value === true) {
- // For now, ES expects an empty object when defining a data stream
- // https://github.com/elastic/elasticsearch/pull/59317
- return {};
- }
- },
- 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,
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 18c74716a35b6..3dab4113e6965 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,7 +20,14 @@ export const templateSchema = schema.object({
})
),
composedOf: schema.maybe(schema.arrayOf(schema.string())),
- dataStream: schema.maybe(schema.object({}, { unknowns: 'allow' })),
+ dataStream: schema.maybe(
+ schema.object(
+ {
+ hidden: schema.maybe(schema.boolean()),
+ },
+ { unknowns: 'allow' }
+ )
+ ),
_meta: schema.maybe(schema.object({}, { unknowns: 'allow' })),
ilmPolicy: schema.maybe(
schema.object({
diff --git a/x-pack/plugins/index_management/test/fixtures/template.ts b/x-pack/plugins/index_management/test/fixtures/template.ts
index 016100faea601..90f556794a5d9 100644
--- a/x-pack/plugins/index_management/test/fixtures/template.ts
+++ b/x-pack/plugins/index_management/test/fixtures/template.ts
@@ -53,6 +53,7 @@ export const getTemplate = ({
order = getRandomNumber(),
indexPatterns = [],
template: { settings, aliases, mappings } = {},
+ dataStream,
hasDatastream = false,
isLegacy = false,
type = 'default',
@@ -73,12 +74,13 @@ export const getTemplate = ({
mappings,
settings,
},
+ dataStream,
hasSettings: objHasProperties(settings),
hasMappings: objHasProperties(mappings),
hasAliases: objHasProperties(aliases),
_kbnMeta: {
type,
- hasDatastream,
+ hasDatastream: dataStream !== undefined ? true : hasDatastream,
isLegacy,
},
};