import { saveAs } from '@elastic/filesaver' ; import type { MlApiServices } from '../../../services/ml_api_service' ; import type { JobType } from '../../../../../common/types/saved_objects' ; import type { Job , Datafeed } from '../../../../../common/types/anomaly_detection_jobs' ; import type { DataFrameAnalyticsConfig } from '../../../../../common/types/data_frame_analytics' ; import { GLOBAL_CALENDAR } from '../../../../../common/constants/calendars' ; export type JobDependencies = Array < { jobId : string ; calendarIds : string [ ] ; filterIds : string [ ] ; } > ; export type FiltersPerJob = Array < { jobId : string ; filterIds : string [ ] ; } > ; type ExportableConfigs = Array < { job ? : Job ; datafeed ? : Datafeed ; } | undefined > | DataFrameAnalyticsConfig [ ] ; export class JobsExportService { constructor ( private _mlApiServices ) { } public async exportAnomalyDetectionJobs ( jobIds ) { const configs = await Promise . all ( jobIds . map ( this . _mlApiServices . jobs . jobForCloning ) ) ; this . _export ( configs , 'anomaly-detector' ) ; } public async exportDataframeAnalyticsJobs ( jobIds ) { const { data_frame_analytics : configs } = await this . _mlApiServices . dataFrameAnalytics . getDataFrameAnalytics ( jobIds . join ( ',' ) , true ) ; this . _export ( configs , 'data-frame-analytics' ) ; } private _export ( configs , jobType ) { const configsForExport = configs . length === 1 ? configs [ 0 ] : configs ; const blob = new Blob ( [ JSON . stringify ( configsForExport , null , 2 ) ] , { type : 'application/json' , } ) ; const fileName = this . _createFileName ( jobType ) ; saveAs ( blob , fileName ) ; } private _createFileName ( jobType ) { return ( ( jobType === 'anomaly-detector' ? 'anomaly_detection' : 'data_frame_analytics' ) + '_jobs.json' ) ; } public async getJobDependencies ( jobs ) { const calendars = await this . _mlApiServices . calendars ( ) ; const groups = jobs . reduce ( ( acc , cur ) => { if ( Array . isArray ( cur . groups ) ) { cur . groups . forEach ( ( g ) => { if ( acc [ g ] === undefined ) { acc [ g ] = [ ] ; } acc [ g ] . push ( cur . job_id ) ; } ) ; } return acc ; } , { } as Record < string , string [ ] > ) ; const isGroup = ( id ) => groups [ id ] !== undefined ; const calendarsPerJob = calendars . reduce ( ( acc , cur ) => { cur . job_ids . forEach ( ( jId ) => { if ( jId === GLOBAL_CALENDAR ) { jobs . forEach ( ( j ) => { if ( acc [ j . job_id ] === undefined ) { acc [ j . job_id ] = [ ] ; } acc [ j . job_id ] . push ( cur . calendar_id ) ; } ) ; } else if ( isGroup ( jId ) ) { groups [ jId ] . forEach ( ( jId2 ) => { if ( acc [ jId2 ] === undefined ) { acc [ jId2 ] = [ ] ; } acc [ jId2 ] . push ( cur . calendar_id ) ; } ) ; } else { if ( acc [ jId ] === undefined ) { acc [ jId ] = [ ] ; } acc [ jId ] . push ( cur . calendar_id ) ; } } ) ; return acc ; } , { } as Record < string , string [ ] > ) ; const filtersPerJob = jobs . reduce ( ( acc , cur ) => { if ( acc [ cur . job_id ] === undefined ) { acc [ cur . job_id ] = [ ] ; } cur . analysis_config . detectors . forEach ( ( d ) => { if ( d . custom_rules !== undefined ) { d . custom_rules . forEach ( ( r ) => { if ( r . scope !== undefined ) { Object . values ( r . scope ) . forEach ( ( scope ) => { acc [ cur . job_id ] . push ( scope . filter_id ) ; } ) ; } } ) ; } } ) ; return acc ; } , { } as Record < string , string [ ] > ) ; return jobs . map ( ( j ) => { const jobId = j . job_id ; return { jobId , calendarIds : [ ... new Set ( calendarsPerJob [ jobId ] ) ] ?? [ ] , filterIds : [ ... new Set ( filtersPerJob [ jobId ] ) ] ?? [ ] , } ; } ) ; } }