diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts index 3ab8efda27fac..0f3a598df9762 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/template/template.ts @@ -142,7 +142,7 @@ export function getTemplate({ return template; } -const getBaseEsComponents = (type: string, isIndexModeTimeSeries: boolean): string[] => { +export const getBaseEsComponents = (type: string, isIndexModeTimeSeries: boolean): string[] => { if (type === 'metrics') { if (isIndexModeTimeSeries) { return [STACK_COMPONENT_TEMPLATE_METRICS_TSDB_SETTINGS]; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/install.test.ts new file mode 100644 index 0000000000000..2c75660c2e26c --- /dev/null +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/install.test.ts @@ -0,0 +1,35 @@ +/* + * 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 { getTransformDestinationDataType } from './install'; + +describe('getTransformDestinationDataType', () => { + test('should return "logs" when destinationIndex is falsy', () => { + expect(getTransformDestinationDataType(undefined)).toBe('logs'); + expect(getTransformDestinationDataType('')).toBe('logs'); + expect(getTransformDestinationDataType()).toBe('logs'); + }); + + test('should return the expected data type when destinationIndex starts with with one of them and matches the pattern', () => { + expect(getTransformDestinationDataType('logs-endpoint-default')).toBe('logs'); + expect(getTransformDestinationDataType('metrics-system-default')).toBe('metrics'); + expect(getTransformDestinationDataType('traces-apm-default')).toBe('traces'); + expect(getTransformDestinationDataType('synthetics-browser-default')).toBe('synthetics'); + expect(getTransformDestinationDataType('metrics-system@test-default')).toBe('metrics'); + }); + + test('should return "logs" for non-matching patterns', () => { + expect(getTransformDestinationDataType('custom-index-name')).toBe('logs'); + expect(getTransformDestinationDataType('elasticsearch-index')).toBe('logs'); + expect(getTransformDestinationDataType('random-string')).toBe('logs'); + expect(getTransformDestinationDataType('metrics-single')).toBe('logs'); + expect(getTransformDestinationDataType('traces')).toBe('logs'); + expect(getTransformDestinationDataType('synthetics-')).toBe('logs'); + expect(getTransformDestinationDataType('TRACES-apm-default')).toBe('logs'); + expect(getTransformDestinationDataType('metrics-system.template')).toBe('logs'); + expect(getTransformDestinationDataType('metrics.test.default')).toBe('logs'); + }); +}); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/install.ts index bd88faea430b1..cea08d5ceea20 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/install.ts @@ -42,6 +42,7 @@ import type { RegistryElasticsearch, AssetsMap, } from '../../../../../common/types/models'; +import { getBaseEsComponents } from '../template/template'; import { getInstallation } from '../../packages'; import { retryTransientEsErrors } from '../retry'; import { isUserSettingsTemplate } from '../template/utils'; @@ -66,6 +67,7 @@ interface TransformModuleBase { transformModuleId?: string; } interface DestinationIndexTemplateInstallation extends TransformModuleBase { + type: 'logs' | 'metrics' | 'traces' | 'synthetics'; installationName: string; _meta: ESAssetMetadata; template: IndexTemplate['template']; @@ -133,9 +135,11 @@ const installLegacyTransformsAssets = async ( const transforms: TransformInstallation[] = transformPaths.map((path: string) => { const content = JSON.parse(getAssetFromAssetsMap(transformAssetsMap, path).toString('utf-8')); + const destinationIndex = content.dest?.index as string | undefined; content._meta = getESAssetMetadata({ packageName: packageInstallContext.packageInfo.name }); return { + type: getTransformDestinationDataType(destinationIndex), installationName: getLegacyTransformNameForInstallation( packageInstallContext.packageInfo, path, @@ -207,12 +211,14 @@ const processTransformAssetsPerModule = async ( const packageAssets = transformsSpecifications.get(transformModuleId); const content = load(getAssetFromAssetsMap(transformAssetsMap, path).toString('utf-8')); + const destinationIndex = content.dest?.index as string | undefined; // Handling fields.yml and all other files within 'fields' folder if (fileName === TRANSFORM_SPECS_TYPES.FIELDS || isFields(path)) { const templateName = getTransformAssetNameForInstallation( installablePackage, transformModuleId, + destinationIndex, 'template' ); const indexToModify = destinationIndexTemplates.findIndex( @@ -221,9 +227,11 @@ const processTransformAssetsPerModule = async ( const template = { transformModuleId, _meta: getESAssetMetadata({ packageName: installablePackage.name }), + type: getTransformDestinationDataType(destinationIndex), installationName: getTransformAssetNameForInstallation( installablePackage, transformModuleId, + destinationIndex, 'template' ), template: {}, @@ -275,6 +283,7 @@ const processTransformAssetsPerModule = async ( const installationName = getTransformAssetNameForInstallation( installablePackage, transformModuleId, + destinationIndex, // transform_id is versioned by fleet_transform_version and not by package version `default-${transformVersion}` ); @@ -358,6 +367,7 @@ const processTransformAssetsPerModule = async ( const templateName = getTransformAssetNameForInstallation( installablePackage, transformModuleId, + destinationIndex, 'template' ); const indexToModify = destinationIndexTemplates.findIndex( @@ -366,9 +376,11 @@ const processTransformAssetsPerModule = async ( const template = { transformModuleId, _meta: getESAssetMetadata({ packageName: installablePackage.name }), + type: getTransformDestinationDataType(destinationIndex), installationName: getTransformAssetNameForInstallation( installablePackage, transformModuleId, + destinationIndex, 'template' ), template: content.destination_index_template, @@ -550,6 +562,7 @@ const installTransformsAssets = async ( 'index_template.mappings': destinationIndexTemplate.template.mappings, }; + const esBaseComponents = getBaseEsComponents(destinationIndexTemplate.type, false); const componentTemplates = buildComponentTemplates({ mappings: customMappings, templateName: destinationIndexTemplate.installationName, @@ -583,6 +596,7 @@ const installTransformsAssets = async ( ], _meta: destinationIndexTemplate._meta, composed_of: [ + ...esBaseComponents, ...Object.keys(componentTemplates), STACK_COMPONENT_TEMPLATE_ECS_MAPPINGS, ], @@ -882,12 +896,28 @@ const getLegacyTransformNameForInstallation = ( return `${installablePackage.name}.${folderName}-${filename}${suffix ? '-' + suffix : ''}`; }; +// If destinationIndex is defined, use it to derive the data type depending on if it matches one of the known +// patterns with preset component templates. Defaults to `logs` type if no destinationIndex is provided. +export const getTransformDestinationDataType = ( + destinationIndex?: string +): DestinationIndexTemplateInstallation['type'] => { + const dataType = destinationIndex + ? destinationIndex.match(/^(logs|metrics|traces|synthetics)-.*-.*$/) + ? destinationIndex.split('-')[0] + : 'logs' + : 'logs'; + return dataType as DestinationIndexTemplateInstallation['type']; +}; + const getTransformAssetNameForInstallation = ( installablePackage: InstallablePackage, transformModuleId: string, + destinationIndex?: string, suffix?: string ) => { - return `logs-${installablePackage.name}.${transformModuleId}${suffix ? '-' + suffix : ''}`; + return `${getTransformDestinationDataType(destinationIndex)}-${ + installablePackage.name + }.${transformModuleId}${suffix ? '-' + suffix : ''}`; }; const getTransformFolderAndFileNames = (installablePackage: InstallablePackage, path: string) => { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/transforms.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/transforms.test.ts index 5860b82f96154..76e11102ca9b9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/transforms.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/transforms.test.ts @@ -385,6 +385,8 @@ _meta: { _meta: meta, composed_of: [ + 'logs@mappings', + 'logs@settings', 'logs-endpoint.metadata_current-template@package', 'endpoint@custom', 'logs-endpoint.metadata_current-template@custom', @@ -674,6 +676,8 @@ _meta: { _meta: meta, composed_of: [ + 'logs@mappings', + 'logs@settings', 'logs-endpoint.metadata_current-template@package', 'endpoint@custom', 'logs-endpoint.metadata_current-template@custom', @@ -940,6 +944,8 @@ _meta: { _meta: meta, composed_of: [ + 'logs@mappings', + 'logs@settings', 'logs-endpoint.metadata_current-template@package', 'endpoint@custom', 'logs-endpoint.metadata_current-template@custom',