import type { ElasticsearchClient , Logger , LogMeta } from 'kibana/server' ; import sinon from 'sinon' ; import expect from '@kbn/expect' ; import { mappingFromFieldMap } from '../../../../../plugins/rule_registry/common/mapping_from_field_map' ; import { AlertConsumers , ALERT_REASON , ALERT_UUID , } from '../../../../../plugins/rule_registry/common/technical_rule_data_field_names' ; import { createLifecycleExecutor , WrappedLifecycleRuleState , } from '../../../../../plugins/rule_registry/server/utils/create_lifecycle_executor' ; import type { FtrProviderContext } from '../../../common/ftr_provider_context' ; import { Dataset , IRuleDataClient , RuleDataService , } from '../../../../../plugins/rule_registry/server' ; import { MockRuleParams , MockRuleState , MockAlertContext , MockAlertState , MockAllowedActionGroups , } from '../../../common/types' ; import { AlertExecutorOptions as RuleExecutorOptions } from '../../../../../plugins/alerting/server' ; import { cleanupRegistryIndices } from '../../../common/lib/helpers/cleanup_registry_indices' ; export default function createLifecycleExecutorApiTest ( { getService } ) { const es = getService ( 'cluster_client' ) ; const log = getService ( 'log' ) ; const fakeLogger = < Meta extends LogMeta = LogMeta > ( msg , meta ? ) => meta ? log . debug ( msg , meta ) : log . debug ( msg ) ; const logger = { trace : fakeLogger , debug : fakeLogger , info : fakeLogger , warn : fakeLogger , error : fakeLogger , fatal : fakeLogger , log : sinon . stub ( ) , get : sinon . stub ( ) , } as Logger ; const getClusterClient = ( ) => { const client = es as ElasticsearchClient ; return Promise . resolve ( client ) ; } ; describe ( 'createLifecycleExecutor' , ( ) => { let ruleDataClient ; before ( async ( ) => { const ruleDataService = new RuleDataService ( { getClusterClient , logger , kibanaVersion : '8.0.0' , isWriteEnabled : true , isWriterCacheEnabled : false , disabledRegistrationContexts : [ ] as string [ ] , } ) ; ruleDataService . initializeService ( ) ; ruleDataClient = ruleDataService . initializeIndex ( { feature : AlertConsumers . OBSERVABILITY , registrationContext : 'observability.test' , dataset : Dataset . alerts , componentTemplateRefs : [ ] , componentTemplates : [ { name : 'mappings' , mappings : mappingFromFieldMap ( { testObject : { type : 'object' , required : false , array : false , } , } , false ) , } , ] , } ) ; } ) ; after ( async ( ) => { cleanupRegistryIndices ( getService , ruleDataClient ) ; } ) ; it ( 'should work with object fields' , async ( ) => { const id = 'host-01' ; const createLifecycleRuleExecutor = createLifecycleExecutor ( logger , ruleDataClient ) ; const executor = createLifecycleRuleExecutor < MockRuleParams , MockRuleState , MockAlertState , MockAlertContext , MockAllowedActionGroups > ( async function ( options ) { const { services , state : previousState } = options ; const { alertWithLifecycle } = services ; const state = previousState . testObject ? { ... previousState , testObject : { ... previousState . testObject , values : [ ... previousState . testObject . values , { name : 'count' , value : previousState . testObject . values . length + 1 } , ] , } , } : { ... previousState , testObject : { id , values : [ { name : 'count' , value : 1 } ] , host : { name : id , } , } , } ; alertWithLifecycle ( { id , fields : { [ ALERT_REASON ] : 'Test alert is firing' , ... state , } , } ) ; return Promise . resolve ( state ) ; } ) ; const options = { alertId : id , spaceId : 'default' , tags : [ 'test' ] , startedAt : new Date ( ) , rule : { name : 'test rule' , ruleTypeId : 'observability.test.fake' , ruleTypeName : 'test' , consumer : 'observability' , producer : 'observability.test' , } , services : { alertInstanceFactory : sinon . stub ( ) , shouldWriteAlerts : sinon . stub ( ) . returns ( true ) , } , } as unknown as RuleExecutorOptions < MockRuleParams , WrappedLifecycleRuleState < MockRuleState > , { [ x ] : unknown ; } , { [ x ] : unknown ; } , string > ; const results = await executor ( options ) ; expect ( results . wrapped ) . to . eql ( { testObject : { host : { name : 'host-01' } , id : 'host-01' , values : [ { name : 'count' , value : 1 } ] , } , } ) ; await es . indices . refresh ( { index : `${ ruleDataClient . indexName }*` } ) ; const nextResults = await executor ( { ... options , state : results } ) ; expect ( nextResults . wrapped ) . to . eql ( { testObject : { host : { name : 'host-01' } , id : 'host-01' , values : [ { name : 'count' , value : 1 } , { name : 'count' , value : 2 } , ] , } , } ) ; await es . indices . refresh ( { index : `${ ruleDataClient . indexName }*` } ) ; const response = await ruleDataClient . getReader ( ) . search ( { body : { query : { bool : { filter : [ { term : { [ ALERT_UUID ] : nextResults . trackedAlerts [ 'host-01' ] . alertUuid , } , } , ] , } , } , } , } ) ; const source = response . hits . hits [ 0 ] . _source as any ; expect ( source . testObject ) . to . eql ( nextResults . wrapped && nextResults . wrapped . testObject ) ; } ) ; } ) ; }