diff --git a/public/components/application_analytics/__tests__/__snapshots__/log_config.test.tsx.snap b/public/components/application_analytics/__tests__/__snapshots__/log_config.test.tsx.snap index 92fc9e21d..4422eb9c1 100644 --- a/public/components/application_analytics/__tests__/__snapshots__/log_config.test.tsx.snap +++ b/public/components/application_analytics/__tests__/__snapshots__/log_config.test.tsx.snap @@ -20,6 +20,9 @@ exports[`Log Config component renders empty log config 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -687,6 +690,9 @@ exports[`Log Config component renders with query 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { diff --git a/public/components/application_analytics/__tests__/__snapshots__/service_config.test.tsx.snap b/public/components/application_analytics/__tests__/__snapshots__/service_config.test.tsx.snap index 4d3120efd..e3a9c049f 100644 --- a/public/components/application_analytics/__tests__/__snapshots__/service_config.test.tsx.snap +++ b/public/components/application_analytics/__tests__/__snapshots__/service_config.test.tsx.snap @@ -20,6 +20,9 @@ exports[`Service Config component renders empty service config 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -1230,6 +1233,9 @@ exports[`Service Config component renders with one service selected 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { diff --git a/public/components/application_analytics/__tests__/__snapshots__/trace_config.test.tsx.snap b/public/components/application_analytics/__tests__/__snapshots__/trace_config.test.tsx.snap index c55c9eff0..08c6d4552 100644 --- a/public/components/application_analytics/__tests__/__snapshots__/trace_config.test.tsx.snap +++ b/public/components/application_analytics/__tests__/__snapshots__/trace_config.test.tsx.snap @@ -19,6 +19,9 @@ exports[`Trace Config component renders empty trace config 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -942,6 +945,9 @@ exports[`Trace Config component renders with one trace selected 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { diff --git a/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap b/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap index 6cbd8f8eb..26834fc0e 100644 --- a/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap +++ b/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap @@ -1167,6 +1167,9 @@ exports[`Panels View Component renders panel view container with visualizations ], }, "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -3069,6 +3072,9 @@ exports[`Panels View Component renders panel view container with visualizations ], }, "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -3527,6 +3533,9 @@ exports[`Panels View Component renders panel view container without visualizatio ], }, "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -5313,6 +5322,9 @@ exports[`Panels View Component renders panel view container without visualizatio ], }, "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { diff --git a/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap b/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap index cd8bc1e16..7562b5821 100644 --- a/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap +++ b/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap @@ -177,6 +177,9 @@ exports[`Panel Grid Component renders panel grid component with empty visualizat ], }, "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { diff --git a/public/components/getting_started/components/getting_started_collectData.tsx b/public/components/getting_started/components/getting_started_collectData.tsx index 0028486cc..8a69053aa 100644 --- a/public/components/getting_started/components/getting_started_collectData.tsx +++ b/public/components/getting_started/components/getting_started_collectData.tsx @@ -21,6 +21,7 @@ import { EuiButton, EuiIcon, EuiCard, + EuiSelectableOption, } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; @@ -52,7 +53,7 @@ interface CollectAndShipDataProps { selectedDataSourceLabel: string; } -interface CollectorOption { +export interface CollectorOption { label: string; value: string; } @@ -70,6 +71,21 @@ export const CollectAndShipData: React.FC = ({ const [collectorOptions, setCollectorOptions] = useState([]); const [patternsContent, setPatternsContent] = useState([]); + const getTelemetryOption = (collectionMethodOtel: string) => { + switch (collectionMethodOtel) { + case cardTwo: + return { label: 'Open Telemetry', value: 'otelMetrics' }; + case cardThree: + return { label: 'Open Telemetry', value: 'otelTraces' }; + default: + return { label: 'Open Telemetry', value: 'otelLogs' }; + } + }; + + const [selectedIntegration, setSelectedIntegration] = useState< + Array> + >([getTelemetryOption(cardOne)]); + const technologyJsonMap: Record = { otelLogs: otelJsonLogs, otelMetrics: otelJsonMetrics, @@ -122,13 +138,14 @@ export const CollectAndShipData: React.FC = ({ }; }, [specificMethod]); - const handleSpecificMethodChange = (newOption: any) => { + const handleSpecificMethodChange = (newOption: Array>) => { const selectedOptionValue = newOption[0]?.value; if (selectedOptionValue === specificMethod) { return; } + setSelectedIntegration(newOption); setSpecificMethod(selectedOptionValue); setSelectedWorkflow(''); setGettingStarted(null); @@ -138,7 +155,8 @@ export const CollectAndShipData: React.FC = ({ // Auto-select first collector if nothing is selected and a collection method is set useEffect(() => { if (collectorOptions.length > 0 && !specificMethod && collectionMethod) { - handleSpecificMethodChange([{ value: collectorOptions[0].value }]); + const telemetryOption = getTelemetryOption(collectionMethod); + handleSpecificMethodChange([{ ...telemetryOption }]); } }, [collectorOptions, specificMethod, collectionMethod]); @@ -151,17 +169,19 @@ export const CollectAndShipData: React.FC = ({ if (value === cardOne) { setCollectorOptions([ - { label: 'Open Telemetry', value: 'otelLogs' }, + getTelemetryOption(cardOne), { label: 'Nginx', value: 'nginx' }, { label: 'Java', value: 'java' }, { label: 'Python', value: 'python' }, { label: 'Golang', value: 'golang' }, ]); } else if (value === cardTwo) { - setCollectorOptions([{ label: 'Open Telemetry', value: 'otelMetrics' }]); + setCollectorOptions([getTelemetryOption(cardTwo)]); } else if (value === cardThree) { - setCollectorOptions([{ label: 'Open Telemetry', value: 'otelTraces' }]); + setCollectorOptions([getTelemetryOption(cardThree)]); } + + setSelectedIntegration([getTelemetryOption(value)]); }; const renderSpecificMethodDropdown = () => { @@ -200,7 +220,9 @@ export const CollectAndShipData: React.FC = ({ singleSelection={{ asPlainText: true }} options={optionsWithIcons} selectedOptions={selectedOption ? [selectedOption] : []} - onChange={(newOptions) => handleSpecificMethodChange(newOptions)} + onChange={(newOptions) => + handleSpecificMethodChange(newOptions as Array>) + } renderOption={(option) => (
{option.prepend} @@ -347,7 +369,15 @@ export const CollectAndShipData: React.FC = ({ { - await UploadAssets(specificMethod, selectedDataSourceId, selectedDataSourceLabel); + await UploadAssets( + specificMethod, + selectedDataSourceId, + selectedDataSourceLabel, + technologyJsonMap[specificMethod]?.['getting-started']?.schema || + technologyJsonMap[specificMethod]?.schema || + [], + selectedIntegration + ); }} fill > diff --git a/public/components/getting_started/components/utils.tsx b/public/components/getting_started/components/utils.tsx index 3c50f3072..420ce5c43 100644 --- a/public/components/getting_started/components/utils.tsx +++ b/public/components/getting_started/components/utils.tsx @@ -3,8 +3,27 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { MappingTypeMapping } from '@opensearch-project/opensearch/api/types'; +import { EuiSelectableOption } from '@elastic/eui'; import { coreRefs } from '../../../framework/core_refs'; import { useToast } from '../../../../public/components/common/toast'; +import { CollectorOption } from './getting_started_collectData'; + +export interface ICollectorIndexTemplate { + name: string; + templatePath: string; + template: MappingTypeMapping; +} + +export interface ICollectorSchema { + alias: string; + content: string; + description: string; + 'index-pattern-name': string; + type: string; + 'index-template': string; + info: string[]; +} const fetchAssets = async (tutorialId: string, assetFilter?: 'dashboards' | 'indexPatterns') => { const assetFilterParam = assetFilter ? `${assetFilter}/` : ''; @@ -20,16 +39,51 @@ const fetchAssets = async (tutorialId: string, assetFilter?: 'dashboards' | 'ind return responeData; }; -export const UploadAssets = async (tutorialId: string, mdsId: string, mdsLabel: string) => { +export const UploadAssets = async ( + tutorialId: string, + mdsId: string, + mdsLabel: string, + schema: ICollectorSchema[], + selectedIntegration: Array> +) => { const { setToast } = useToast(); const http = coreRefs.http; + let curIntegration: string | undefined; + if (selectedIntegration !== undefined) { + if (/^otel[A-Za-z]+$/i.test(selectedIntegration[0].value)) { + curIntegration = 'otel-services'; + } else if (selectedIntegration[0].value === 'nginx') { + curIntegration = selectedIntegration[0].value; + } + } + try { + // Auto-generate index templates based on the selected integration + let templates: ICollectorIndexTemplate[] = []; + if (curIntegration !== undefined) { + const indexTemplateMappings = await http!.get( + `/api/integrations/repository/${curIntegration}/schema` + ); + templates = schema.reduce((acc: ICollectorIndexTemplate[], sh) => { + const templateMapping = indexTemplateMappings?.data?.mappings?.[sh.type.toLowerCase()]; + if (!!templateMapping) { + acc.push({ + name: sh.content.match(/[^/]+$/)?.[0] || '', + templatePath: sh.content.match(/PUT\s+(.+)/)?.[1] || '', + template: templateMapping, + }); + } + return acc; + }, []); + } + const response = await http!.post(`/api/observability/gettingStarted/createAssets`, { body: JSON.stringify({ mdsId, mdsLabel, tutorialId, + indexTemplates: templates, }), }); diff --git a/public/components/metrics/view/__tests__/__snapshots__/metrics_grid.test.tsx.snap b/public/components/metrics/view/__tests__/__snapshots__/metrics_grid.test.tsx.snap index ea4b81948..cb4832d47 100644 --- a/public/components/metrics/view/__tests__/__snapshots__/metrics_grid.test.tsx.snap +++ b/public/components/metrics/view/__tests__/__snapshots__/metrics_grid.test.tsx.snap @@ -30,6 +30,9 @@ exports[`Metrics Grid Component renders Metrics Grid Component 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -204,6 +207,9 @@ exports[`Metrics Grid Component renders Metrics Grid Component 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { diff --git a/public/components/trace_analytics/components/dashboard/__tests__/__snapshots__/dashboard.test.tsx.snap b/public/components/trace_analytics/components/dashboard/__tests__/__snapshots__/dashboard.test.tsx.snap index 979c56df4..a4f6cde40 100644 --- a/public/components/trace_analytics/components/dashboard/__tests__/__snapshots__/dashboard.test.tsx.snap +++ b/public/components/trace_analytics/components/dashboard/__tests__/__snapshots__/dashboard.test.tsx.snap @@ -33,6 +33,9 @@ exports[`Dashboard component renders dashboard 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -423,6 +426,9 @@ exports[`Dashboard component renders dashboard 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -1285,6 +1291,9 @@ exports[`Dashboard component renders empty dashboard 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -1674,6 +1683,9 @@ exports[`Dashboard component renders empty dashboard 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -2536,6 +2548,9 @@ exports[`Dashboard component renders empty jaeger dashboard 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -2927,6 +2942,9 @@ exports[`Dashboard component renders empty jaeger dashboard 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { diff --git a/public/components/trace_analytics/components/services/__tests__/__snapshots__/services.test.tsx.snap b/public/components/trace_analytics/components/services/__tests__/__snapshots__/services.test.tsx.snap index 876722ce8..3d33b9a4b 100644 --- a/public/components/trace_analytics/components/services/__tests__/__snapshots__/services.test.tsx.snap +++ b/public/components/trace_analytics/components/services/__tests__/__snapshots__/services.test.tsx.snap @@ -33,6 +33,9 @@ exports[`Services component renders empty services page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -261,6 +264,9 @@ exports[`Services component renders empty services page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -2326,6 +2332,9 @@ exports[`Services component renders jaeger services page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -2554,6 +2563,9 @@ exports[`Services component renders jaeger services page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -3115,7 +3127,7 @@ exports[`Services component renders jaeger services page 1`] = ` xmlns="http://www.w3.org/2000/svg" > @@ -4048,6 +4060,9 @@ exports[`Services component renders services page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -4275,6 +4290,9 @@ exports[`Services component renders services page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -4835,7 +4853,7 @@ exports[`Services component renders services page 1`] = ` xmlns="http://www.w3.org/2000/svg" > diff --git a/public/components/trace_analytics/components/traces/__tests__/__snapshots__/traces.test.tsx.snap b/public/components/trace_analytics/components/traces/__tests__/__snapshots__/traces.test.tsx.snap index fdafb00fd..83b3f6fb6 100644 --- a/public/components/trace_analytics/components/traces/__tests__/__snapshots__/traces.test.tsx.snap +++ b/public/components/trace_analytics/components/traces/__tests__/__snapshots__/traces.test.tsx.snap @@ -33,6 +33,9 @@ exports[`Traces component renders empty traces page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -270,6 +273,9 @@ exports[`Traces component renders empty traces page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -2513,6 +2519,9 @@ exports[`Traces component renders jaeger traces page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -2750,6 +2759,9 @@ exports[`Traces component renders jaeger traces page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -3321,7 +3333,7 @@ exports[`Traces component renders jaeger traces page 1`] = ` xmlns="http://www.w3.org/2000/svg" > @@ -4832,6 +4844,9 @@ exports[`Traces component renders traces page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -5068,6 +5083,9 @@ exports[`Traces component renders traces page 1`] = ` "getHelpExtension$": [MockFunction], "getIsNavDrawerLocked$": [MockFunction], "getIsVisible$": [MockFunction], + "globalSearch": Object { + "getAllSearchCommands": [MockFunction], + }, "logos": Object { "AnimatedMark": Object { "dark": Object { @@ -5638,7 +5656,7 @@ exports[`Traces component renders traces page 1`] = ` xmlns="http://www.w3.org/2000/svg" > diff --git a/server/routes/getting_started/getting_started_router.ts b/server/routes/getting_started/getting_started_router.ts index 4bdd7dfb8..596464ae5 100644 --- a/server/routes/getting_started/getting_started_router.ts +++ b/server/routes/getting_started/getting_started_router.ts @@ -12,7 +12,7 @@ import { SavedObject, } from '../../../../../src/core/server'; import { createSavedObjectsStreamFromNdJson } from '../../../../../src/core/server/saved_objects/routes/utils'; -import { loadAssetsFromFile } from './helper'; +import { loadAssetsFromFile, createAllTemplatesSettled } from './helper'; import { getWorkspaceState } from '../../../../../src/core/server/utils'; import { TutorialId } from '../../../common/constants/getting_started_routes'; @@ -99,6 +99,14 @@ export function registerGettingStartedRoutes(router: IRouter) { mdsId: schema.string(), mdsLabel: schema.string(), tutorialId: schema.string(), + indexTemplates: schema.arrayOf( + schema.object({ + name: schema.string(), + templatePath: schema.string(), + template: schema.recordOf(schema.string(), schema.any()), + }), + { defaultValue: [] } + ), }), }, }, @@ -108,10 +116,15 @@ export function registerGettingStartedRoutes(router: IRouter) { response ): Promise> => { try { - const { mdsId, mdsLabel, tutorialId } = request.body; + const { mdsId, mdsLabel, tutorialId, indexTemplates } = request.body; const { requestWorkspaceId } = getWorkspaceState(request); const fileData = await loadAssetsFromFile(tutorialId as TutorialId); + // create related index templates + if (indexTemplates.length > 0) { + await createAllTemplatesSettled(context, indexTemplates, mdsId); + } + const objects = await createSavedObjectsStreamFromNdJson(Readable.from(fileData)); const loadedObjects = await objects.toArray(); diff --git a/server/routes/getting_started/helper.ts b/server/routes/getting_started/helper.ts index c9375301f..879e608b1 100644 --- a/server/routes/getting_started/helper.ts +++ b/server/routes/getting_started/helper.ts @@ -5,12 +5,14 @@ import fs from 'fs'; import path from 'path'; +import { MappingTypeMapping } from '@opensearch-project/opensearch/api/types'; import { COMPONENT_MAP, VERSION_MAP, SIGNAL_MAP, TutorialId, } from '../../../common/constants/getting_started_routes'; +import { RequestHandlerContext } from '../../../../../src/core/server'; export const assetMapper = (tutorialId: TutorialId): string => { const component = COMPONENT_MAP[tutorialId] || 'default-component'; @@ -30,3 +32,46 @@ export const loadAssetsFromFile = async (tutorialId: TutorialId) => { throw new Error(`Error loading asset: ${tutorialId}`); } }; + +export const createAllTemplatesSettled = async ( + context: RequestHandlerContext, + indexTemplates: Array<{ name: string; template: MappingTypeMapping; templatePath: string }>, + dataSourceMDSId: string +) => { + const results = await Promise.allSettled( + indexTemplates.map(({ name, template, templatePath }) => + createIndexTemplate(context, name, template, dataSourceMDSId, templatePath) + ) + ); + + return results.map((result, index) => { + const templateName = indexTemplates[index].name; + if (result.status === 'fulfilled') { + return { name: templateName, success: true }; + } + return { name: templateName, success: false, reason: result.reason }; + }); +}; + +export const createIndexTemplate = async ( + context: RequestHandlerContext, + name: string, + template: MappingTypeMapping, + dataSourceMDSId: string, + templatePath: string +) => { + try { + const osClient = dataSourceMDSId + ? await context.dataSource.opensearch.getClient(dataSourceMDSId) + : context.core.opensearch.client.asCurrentUser; + + return await osClient.transport.request({ + method: 'PUT', + path: templatePath, + body: template, + }); + } catch (error) { + console.error(`Failed to create index template ${name}:`, error); + throw error; + } +};