import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey' ; import { schema , TypeOf } from '@kbn/config-schema' ; import { SlmPolicyEs , PolicyIndicesResponse } from '../../../common/types' ; import { deserializePolicy , serializePolicy } from '../../../common/lib' ; import { getManagedPolicyNames } from '../../lib' ; import { RouteDependencies , ResolveIndexResponseFromES } from '../../types' ; import { addBasePath } from '../helpers' ; import { nameParameterSchema , policySchema } from './validate_schemas' ; export function registerPolicyRoutes ( { router , license , lib : { wrapEsError , handleEsError } , } ) { router . get ( { path : addBasePath ( 'policies' ) , validate : false } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const managedPolicies = await getManagedPolicyNames ( clusterClient . asCurrentUser ) ; try { const { body : policiesByName } = await clusterClient . asCurrentUser . slm . getLifecycle ( { human : true , } ) ; return res . ok ( { body : { policies : Object . entries ( policiesByName ) . map ( ( [ name , policy ] ) => { return deserializePolicy ( name , policy as SlmPolicyEs , managedPolicies ) ; } ) , } , } ) ; } catch ( e ) { return handleEsError ( { error : e , response : res } ) ; } } ) ) ; router . get ( { path : addBasePath ( 'policy/{name}' ) , validate : { params : nameParameterSchema } } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const { name } = req . params as TypeOf < typeof nameParameterSchema > ; try { const { body : policiesByName } = await clusterClient . asCurrentUser . slm . getLifecycle ( { policy_id : name , human : true , } ) ; const managedPolicies = await getManagedPolicyNames ( clusterClient . asCurrentUser ) ; return res . ok ( { body : { policy : deserializePolicy ( name , policiesByName [ name ] as SlmPolicyEs , managedPolicies ) , } , } ) ; } catch ( e ) { return handleEsError ( { error : e , response : res } ) ; } } ) ) ; router . post ( { path : addBasePath ( 'policies' ) , validate : { body : policySchema } } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const policy = req . body as TypeOf < typeof policySchema > ; const { name } = policy ; try { const { body : policyByName } = await clusterClient . asCurrentUser . slm . getLifecycle ( { policy_id : name , } ) ; if ( policyByName [ name ] ) { return res . conflict ( { body : 'There is already a policy with that name.' } ) ; } } catch ( e ) { } try { const response = await clusterClient . asCurrentUser . slm . putLifecycle ( { policy_id : name , body : serializePolicy ( policy ) as unknown as estypes . SlmPutLifecycleRequest [ 'body' ] , } ) ; return res . ok ( { body : response . body } ) ; } catch ( e ) { return handleEsError ( { error : e , response : res } ) ; } } ) ) ; router . put ( { path : addBasePath ( 'policies/{name}' ) , validate : { params : nameParameterSchema , body : policySchema } , } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const { name } = req . params as TypeOf < typeof nameParameterSchema > ; const policy = req . body as TypeOf < typeof policySchema > ; try { await clusterClient . asCurrentUser . slm . getLifecycle ( { policy_id : name } ) ; const response = await clusterClient . asCurrentUser . slm . putLifecycle ( { policy_id : name , body : serializePolicy ( policy ) as unknown as estypes . SlmPutLifecycleRequest [ 'body' ] , } ) ; return res . ok ( { body : response . body } ) ; } catch ( e ) { return handleEsError ( { error : e , response : res } ) ; } } ) ) ; router . delete ( { path : addBasePath ( 'policies/{name}' ) , validate : { params : nameParameterSchema } } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const { name } = req . params as TypeOf < typeof nameParameterSchema > ; const policyNames = name . split ( ',' ) ; const response = { itemsDeleted : [ ] , errors : [ ] , } ; await Promise . all ( policyNames . map ( ( policyName ) => { return clusterClient . asCurrentUser . slm . deleteLifecycle ( { policy_id : policyName } ) . then ( ( ) => response . itemsDeleted . push ( policyName ) ) . catch ( ( e ) => response . errors . push ( { name : policyName , error : wrapEsError ( e ) , } ) ) ; } ) ) ; return res . ok ( { body : response } ) ; } ) ) ; router . post ( { path : addBasePath ( 'policy/{name}/run' ) , validate : { params : nameParameterSchema } } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const { name } = req . params as TypeOf < typeof nameParameterSchema > ; try { const { body : { snapshot_name : snapshotName } , } = await clusterClient . asCurrentUser . slm . executeLifecycle ( { policy_id : name , } ) ; return res . ok ( { body : { snapshotName } } ) ; } catch ( e ) { return handleEsError ( { error : e , response : res } ) ; } } ) ) ; router . get ( { path : addBasePath ( 'policies/indices' ) , validate : false } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; try { const response = await clusterClient . asCurrentUser . indices . resolveIndex ( { name : '*' , expand_wildcards : 'all' , } ) ; const resolvedIndicesResponse = response . body as ResolveIndexResponseFromES ; const body = { dataStreams : resolvedIndicesResponse . data_streams . map ( ( { name } ) => name ) . sort ( ) , indices : resolvedIndicesResponse . indices . flatMap ( ( index ) => ( index . data_stream ? [ ] : index . name ) ) . sort ( ) , } ; return res . ok ( { body , } ) ; } catch ( e ) { return handleEsError ( { error : e , response : res } ) ; } } ) ) ; router . get ( { path : addBasePath ( 'policies/retention_settings' ) , validate : false } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const { body : { persistent , transient , defaults } , } = await clusterClient . asCurrentUser . cluster . getSettings ( { filter_path : '**.slm.retention*' , include_defaults : true , } ) ; const { slm : retentionSettings } = { ... defaults , ... persistent , ... transient , } ; const retentionSchedule = retentionSettings != null ? retentionSettings . retention_schedule : undefined ; return res . ok ( { body : { retentionSchedule } , } ) ; } ) ) ; const retentionSettingsSchema = schema . object ( { retentionSchedule : schema . string ( ) } ) ; router . put ( { path : addBasePath ( 'policies/retention_settings' ) , validate : { body : retentionSettingsSchema } , } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const { retentionSchedule } = req . body as TypeOf < typeof retentionSettingsSchema > ; try { const response = await clusterClient . asCurrentUser . cluster . putSettings ( { body : { persistent : { slm : { retention_schedule : retentionSchedule , } , } , } , } ) ; return res . ok ( { body : response . body } ) ; } catch ( e ) { return handleEsError ( { error : e , response : res } ) ; } } ) ) ; router . post ( { path : addBasePath ( 'policies/retention' ) , validate : false } , license . guardApiRoute ( async ( ctx , req , res ) => { const { client : clusterClient } = ctx . core . elasticsearch ; const response = await clusterClient . asCurrentUser . slm . executeRetention ( ) ; return res . ok ( { body : response . body } ) ; } ) ) ; }