@@ -16,6 +16,7 @@ import { createAppContextStartContractMock, createPackagePolicyServiceMock } fro
1616import { getPackageInfo } from '../epm/packages' ;
1717import { appContextService , cloudConnectorService } from '..' ;
1818import { agentPolicyService } from '../agent_policy' ;
19+ import { agentlessAgentService } from '../agents/agentless_agent' ;
1920
2021import { AgentlessPoliciesServiceImpl } from './agentless_policies' ;
2122
@@ -310,6 +311,78 @@ describe('AgentlessPoliciesService', () => {
310311
311312 expect ( jest . mocked ( agentPolicyService . delete ) ) . toHaveBeenCalledTimes ( 0 ) ;
312313 } ) ;
314+
315+ it ( 'should clean up orphaned resources when agent policy is not found (404)' , async ( ) => {
316+ const deleteAgentlessAgentSpy = jest
317+ . spyOn ( agentlessAgentService , 'deleteAgentlessAgent' )
318+ . mockResolvedValueOnce ( undefined as any ) ;
319+
320+ jest . mocked ( agentPolicyService . get ) . mockRejectedValueOnce ( {
321+ output : { statusCode : 404 } ,
322+ } ) ;
323+
324+ packagePolicyService . findAllForAgentPolicy . mockResolvedValueOnce ( [
325+ { id : 'orphaned-pp-1' } ,
326+ { id : 'orphaned-pp-2' } ,
327+ ] as any ) ;
328+
329+ packagePolicyService . delete . mockResolvedValueOnce ( [
330+ { id : 'orphaned-pp-1' , success : true } ,
331+ { id : 'orphaned-pp-2' , success : true } ,
332+ ] as any ) ;
333+
334+ const soClient = savedObjectsClientMock . create ( ) ;
335+ const esClient = elasticsearchServiceMock . createClusterClient ( ) . asInternalUser ;
336+ const logger = loggingSystemMock . createLogger ( ) ;
337+
338+ const agentlessPoliciesService = new AgentlessPoliciesServiceImpl (
339+ packagePolicyService ,
340+ soClient ,
341+ esClient ,
342+ logger
343+ ) ;
344+
345+ await agentlessPoliciesService . deleteAgentlessPolicy ( 'orphaned-policy-id' ) ;
346+
347+ expect ( jest . mocked ( agentPolicyService . delete ) ) . not . toHaveBeenCalled ( ) ;
348+ expect ( packagePolicyService . findAllForAgentPolicy ) . toHaveBeenCalledWith (
349+ soClient ,
350+ 'orphaned-policy-id'
351+ ) ;
352+ expect ( packagePolicyService . delete ) . toHaveBeenCalledWith (
353+ soClient ,
354+ esClient ,
355+ [ 'orphaned-pp-1' , 'orphaned-pp-2' ] ,
356+ expect . objectContaining ( { force : true } )
357+ ) ;
358+ expect ( deleteAgentlessAgentSpy ) . toHaveBeenCalledWith ( 'orphaned-policy-id' ) ;
359+
360+ deleteAgentlessAgentSpy . mockRestore ( ) ;
361+ } ) ;
362+
363+ it ( 'should rethrow non-404 errors from agentPolicyService.get' , async ( ) => {
364+ jest . mocked ( agentPolicyService . get ) . mockRejectedValueOnce ( {
365+ output : { statusCode : 500 } ,
366+ message : 'Internal server error' ,
367+ } ) ;
368+
369+ const soClient = savedObjectsClientMock . create ( ) ;
370+ const esClient = elasticsearchServiceMock . createClusterClient ( ) . asInternalUser ;
371+ const logger = loggingSystemMock . createLogger ( ) ;
372+
373+ const agentlessPoliciesService = new AgentlessPoliciesServiceImpl (
374+ packagePolicyService ,
375+ soClient ,
376+ esClient ,
377+ logger
378+ ) ;
379+
380+ await expect ( ( ) =>
381+ agentlessPoliciesService . deleteAgentlessPolicy ( 'some-policy-id' )
382+ ) . rejects . toEqual ( expect . objectContaining ( { output : { statusCode : 500 } } ) ) ;
383+
384+ expect ( jest . mocked ( agentPolicyService . delete ) ) . not . toHaveBeenCalled ( ) ;
385+ } ) ;
313386 } ) ;
314387
315388 describe ( 'createAgentlessPolicy with cloud connectors' , ( ) => {
0 commit comments