/**
 * The MigrationOpts interface defines the minimum set of data required
 * in order to properly migrate an index. MigrationContext expands this
 * with computed values and values from the index being migrated, and is
 * serves as a central blueprint for what migrations will end up doing.
 */ import { Logger } from 'src/core/server/logging' ; import { MigrationOpenSearchClient } from './migration_opensearch_client' ; import { SavedObjectsSerializer } from '../../serialization' ; import { SavedObjectsTypeMappingDefinitions , SavedObjectsMappingProperties , IndexMapping , } from '../../mappings' ; import { buildActiveMappings } from './build_active_mappings' ; import { VersionedTransformer } from './document_migrator' ; import * as Index from './opensearch_index' ; import { SavedObjectsMigrationLogger , MigrationLogger } from './migration_logger' ; export interface MigrationOpts { batchSize : number ; pollInterval : number ; scrollDuration : string ; client : MigrationOpenSearchClient ; index : string ; log : Logger ; mappingProperties : SavedObjectsTypeMappingDefinitions ; documentMigrator : VersionedTransformer ; serializer : SavedObjectsSerializer ; convertToAliasScript ? : string ; /**
     * If specified, templates matching the specified pattern will be removed
     * prior to running migrations. For example: 'opensearch_dashboards_index_template*'
     */ obsoleteIndexTemplatePattern ? : string ; } internal export interface Context { client : MigrationOpenSearchClient ; alias : string ; source : Index . FullIndexInfo ; dest : Index . FullIndexInfo ; documentMigrator : VersionedTransformer ; log : SavedObjectsMigrationLogger ; batchSize : number ; pollInterval : number ; scrollDuration : string ; serializer : SavedObjectsSerializer ; obsoleteIndexTemplatePattern ? : string ; convertToAliasScript ? : string ; } /**
 * Builds up an uber object which has all of the config options, settings,
 * and various info needed to migrate the source index.
 */ export async function migrationContext ( opts ) { const { log , client } = opts ; const alias = opts . index ; const source = createSourceContext ( await Index . fetchInfo ( client , alias ) , alias ) ; const dest = createDestContext ( source , alias , opts . mappingProperties ) ; return { client , alias , source , dest , log : new MigrationLogger ( log ) , batchSize : opts . batchSize , documentMigrator : opts . documentMigrator , pollInterval : opts . pollInterval , scrollDuration : opts . scrollDuration , serializer : opts . serializer , obsoleteIndexTemplatePattern : opts . obsoleteIndexTemplatePattern , convertToAliasScript : opts . convertToAliasScript , } ; } function createSourceContext ( source , alias ) { if ( source . exists && source . indexName === alias ) { return { ... source , indexName : nextIndexName ( alias , alias ) , } ; } return source ; } function createDestContext ( source , alias , typeMappingDefinitions ) { const targetMappings = disableUnknownTypeMappingFields ( buildActiveMappings ( typeMappingDefinitions ) , source . mappings ) ; return { aliases : { } , exists : false , indexName : nextIndexName ( source . indexName , alias ) , mappings : targetMappings , } ; } param activeMappings param sourceMappings returns export function disableUnknownTypeMappingFields ( activeMappings , sourceMappings ) { const targetTypes = Object . keys ( activeMappings . properties ) ; const disabledTypesProperties = Object . keys ( sourceMappings . properties ) . filter ( ( sourceType ) => { const isObjectType = 'properties' in sourceMappings . properties [ sourceType ] ; return ! targetTypes . includes ( sourceType ) && isObjectType ; } ) . reduce ( ( disabledTypesAcc , sourceType ) => { disabledTypesAcc [ sourceType ] = { dynamic : false , properties : { } } ; return disabledTypesAcc ; } , { } as SavedObjectsMappingProperties ) ; return { ... activeMappings , properties : { ... sourceMappings . properties , ... disabledTypesProperties , ... activeMappings . properties , } , } ; } /**
 * Gets the next index name in a sequence, based on specified current index's info.
 * We're using a numeric counter to create new indices. So, `.opensearch_dashboards_1`, `.opensearch_dashboards_2`, etc
 * There are downsides to this, but it seemed like a simple enough approach.
 */ function nextIndexName ( indexName , alias ) { const indexSuffix = ( indexName . match ( /[\d]+$/ ) || [ ] ) [ 0 ] ; const indexNum = parseInt ( indexSuffix , 10 ) || 0 ; return `${ alias }_${ indexNum + 1 }` ; }