44 * 2.0; you may not use this file except in compliance with the Elastic License 
55 * 2.0. 
66 */ 
7- 
87import  {  loggingSystemMock  }  from  '@kbn/core-logging-server-mocks' ; 
98
10- import  {  PackageNotFoundError ,  RegistryResponseError  }  from  '../../../errors' ; 
9+ import  { 
10+   FleetError , 
11+   PackageNotFoundError , 
12+   RegistryConnectionError , 
13+   RegistryResponseError , 
14+ }  from  '../../../errors' ; 
1115import  *  as  Archive  from  '../archive' ; 
1216
1317import  { 
@@ -18,18 +22,26 @@ import {
1822  getLicensePath , 
1923  fetchCategories , 
2024  fetchList , 
25+   getPackage , 
2126}  from  '.' ; 
2227
23- const  mockLoggerFactory  =  loggingSystemMock . create ( ) ; 
24- const   mockLogger   =   mockLoggerFactory . get ( 'mock logger' ) ; 
28+ const  mockLogger  =  loggingSystemMock . create ( ) . get ( ) ; 
29+ 
2530const  mockGetConfig  =  jest . fn ( ) ; 
2631
2732const  mockGetBundledPackageByName  =  jest . fn ( ) ; 
2833const  mockFetchUrl  =  jest . fn ( ) ; 
34+ const  mockGetResponseStreamWithSize  =  jest . fn ( ) ; 
35+ const  mockStreamToBuffer  =  jest . fn ( ) ; 
36+ const  mockVerifyPackageArchiveSignature  =  jest . fn ( ) ; 
37+ const  mockGetPackageAssetsMapCache  =  jest . fn ( ) ; 
2938
3039const  MockArchive  =  Archive  as  jest . Mocked < typeof  Archive > ; 
3140
3241jest . mock ( '../archive' ) ; 
42+ jest . mock ( './requests' ) ; 
43+ jest . mock ( '../streams' ) ; 
44+ jest . mock ( '../packages/cache' ) ; 
3345
3446jest . mock ( '../..' ,  ( )  =>  ( { 
3547  appContextService : { 
@@ -43,12 +55,31 @@ jest.mock('../..', () => ({
4355
4456jest . mock ( './requests' ,  ( )  =>  ( { 
4557  fetchUrl : ( url : string )  =>  mockFetchUrl ( url ) , 
58+   getResponseStreamWithSize : ( url : string )  =>  mockGetResponseStreamWithSize ( url ) , 
59+ } ) ) ; 
60+ 
61+ jest . mock ( '../streams' ,  ( )  =>  ( { 
62+   streamToBuffer : ( stream : NodeJS . ReadableStream ,  size ?: number )  => 
63+     mockStreamToBuffer ( stream ,  size ) , 
4664} ) ) ; 
4765
4866jest . mock ( '../packages/bundled_packages' ,  ( )  =>  ( { 
4967  getBundledPackageByName : ( name : string )  =>  mockGetBundledPackageByName ( name ) , 
5068} ) ) ; 
5169
70+ jest . mock ( '../packages/package_verification' ,  ( )  =>  ( { 
71+   verifyPackageArchiveSignature : ( 
72+     pkgName : string , 
73+     pkgVersion : string , 
74+     pkgArchiveBuffer : Buffer  |  undefined , 
75+     logger : Logger 
76+   )  =>  mockVerifyPackageArchiveSignature ( pkgName ,  pkgVersion ,  pkgArchiveBuffer ,  logger ) , 
77+ } ) ) ; 
78+ 
79+ jest . mock ( '../packages/cache' ,  ( )  =>  ( { 
80+   getPackageAssetsMapCache : ( )  =>  mockGetPackageAssetsMapCache ( ) , 
81+ } ) ) ; 
82+ 
5283describe ( 'splitPkgKey' ,  ( )  =>  { 
5384  it ( 'throws an error if there is nothing before the delimiter' ,  ( )  =>  { 
5485    expect ( ( )  =>  { 
@@ -225,6 +256,15 @@ describe('fetchInfo', () => {
225256    } ) ; 
226257  } ) ; 
227258
259+   it ( 'falls back to bundled package when isAirGapped config == true' ,  async  ( )  =>  { 
260+     mockGetConfig . mockReturnValue ( { 
261+       isAirGapped : true , 
262+     } ) ; 
263+ 
264+     const  fetchedInfo  =  await  fetchInfo ( 'test-package' ,  '1.0.0' ) ; 
265+     expect ( fetchedInfo ) . toBeTruthy ( ) ; 
266+   } ) ; 
267+ 
228268  it ( 'falls back to bundled package when one exists' ,  async  ( )  =>  { 
229269    const  fetchedInfo  =  await  fetchInfo ( 'test-package' ,  '1.0.0' ) ; 
230270    expect ( fetchedInfo ) . toBeTruthy ( ) ; 
@@ -237,15 +277,6 @@ describe('fetchInfo', () => {
237277      expect ( e ) . toBeInstanceOf ( PackageNotFoundError ) ; 
238278    } 
239279  } ) ; 
240- 
241-   it ( 'falls back to bundled package when isAirGapped config == true' ,  async  ( )  =>  { 
242-     mockGetConfig . mockReturnValue ( { 
243-       isAirGapped : true , 
244-     } ) ; 
245- 
246-     const  fetchedInfo  =  await  fetchInfo ( 'test-package' ,  '1.0.0' ) ; 
247-     expect ( fetchedInfo ) . toBeTruthy ( ) ; 
248-   } ) ; 
249280} ) ; 
250281
251282describe ( 'fetchCategories' ,  ( )  =>  { 
@@ -378,3 +409,200 @@ describe('fetchList', () => {
378409    expect ( callUrl . searchParams . get ( 'kibana.version' ) ) . toBeNull ( ) ; 
379410  } ) ; 
380411} ) ; 
412+ 
413+ describe ( 'getPackage' ,  ( )  =>  { 
414+   const  bundledPackage  =  { 
415+     name : 'testpkg' , 
416+     version : '1.0.0' , 
417+     getBuffer : ( )  =>  Promise . resolve ( Buffer . from ( 'testpkg' ) ) , 
418+   } ; 
419+   const  registryPackage  =  { 
420+     name : 'testpkg' , 
421+     version : '1.0.1' , 
422+     getBuffer : ( )  =>  Promise . resolve ( Buffer . from ( 'testpkg' ) ) , 
423+   } ; 
424+   afterEach ( ( )  =>  { 
425+     jest . resetAllMocks ( ) ; 
426+   } ) ; 
427+ 
428+   it ( 'should return bundled package if isAirGapped = true' ,  async  ( )  =>  { 
429+     mockFetchUrl . mockResolvedValue ( JSON . stringify ( [ registryPackage ] ) ) ; 
430+     mockGetResponseStreamWithSize . mockResolvedValue ( {  stream : { } ,  size : 1000  } ) ; 
431+     mockStreamToBuffer . mockResolvedValue ( Buffer . from ( 'testpkg' ) ) ; 
432+     mockVerifyPackageArchiveSignature . mockResolvedValue ( 'verified' ) ; 
433+     mockGetConfig . mockReturnValue ( { 
434+       isAirGapped : true , 
435+       enabled : true , 
436+       agents : {  enabled : true ,  elasticsearch : { }  } , 
437+     } ) ; 
438+     MockArchive . unpackBufferToAssetsMap . mockReturnValue ( { 
439+       assetsMap : new  Map ( ) , 
440+       paths : [ ] , 
441+       archiveIterator : { } , 
442+     }  as  any ) ; 
443+     MockArchive . generatePackageInfoFromArchiveBuffer . mockReturnValue ( { 
444+       packageInfo : {  name : 'testpkg' ,  version : '1.0.0'  } , 
445+     }  as  any ) ; 
446+ 
447+     mockGetBundledPackageByName . mockResolvedValue ( bundledPackage ) ; 
448+     const  result  =  await  getPackage ( 'testpkg' ,  '1.0.1' ) ; 
449+     expect ( result ) . toEqual ( { 
450+       archiveIterator : { } , 
451+       assetsMap : new  Map ( ) , 
452+       packageInfo : { 
453+         name : 'testpkg' , 
454+         version : '1.0.0' , 
455+       } , 
456+       paths : [ ] , 
457+       verificationResult : 'verified' , 
458+     } ) ; 
459+   } ) ; 
460+ 
461+   it ( 'should return registry package' ,  async  ( )  =>  { 
462+     mockFetchUrl . mockResolvedValue ( JSON . stringify ( [ registryPackage ] ) ) ; 
463+     mockGetResponseStreamWithSize . mockResolvedValue ( {  stream : { } ,  size : 1000  } ) ; 
464+     mockStreamToBuffer . mockResolvedValue ( Buffer . from ( 'testpkg' ) ) ; 
465+     mockVerifyPackageArchiveSignature . mockResolvedValue ( 'verified' ) ; 
466+     MockArchive . unpackBufferToAssetsMap . mockReturnValue ( { 
467+       assetsMap : new  Map ( ) , 
468+       paths : [ ] , 
469+       archiveIterator : { } , 
470+     }  as  any ) ; 
471+     MockArchive . generatePackageInfoFromArchiveBuffer . mockReturnValue ( { 
472+       packageInfo : {  name : 'testpkg' ,  version : '1.0.1'  } , 
473+     }  as  any ) ; 
474+ 
475+     mockGetBundledPackageByName . mockResolvedValue ( undefined ) ; 
476+     const  result  =  await  getPackage ( 'testpkg' ,  '1.0.1' ) ; 
477+     expect ( result ) . toEqual ( { 
478+       archiveIterator : { } , 
479+       assetsMap : new  Map ( ) , 
480+       packageInfo : { 
481+         name : 'testpkg' , 
482+         version : '1.0.1' , 
483+       } , 
484+       paths : [ ] , 
485+       verificationResult : 'verified' , 
486+     } ) ; 
487+   } ) ; 
488+ 
489+   it ( 'should throw if there is an error in fetchArchiveBuffer' ,  async  ( )  =>  { 
490+     mockFetchUrl . mockResolvedValue ( JSON . stringify ( [ registryPackage ] ) ) ; 
491+     mockGetResponseStreamWithSize . mockRejectedValueOnce ( new  FleetError ( 'Error fetching package' ) ) ; 
492+     mockStreamToBuffer . mockResolvedValue ( Buffer . from ( 'testpkg' ) ) ; 
493+     mockVerifyPackageArchiveSignature . mockResolvedValue ( 'verified' ) ; 
494+     MockArchive . unpackBufferToAssetsMap . mockReturnValue ( { 
495+       assetsMap : new  Map ( ) , 
496+       paths : [ ] , 
497+       archiveIterator : { } , 
498+     }  as  any ) ; 
499+     MockArchive . generatePackageInfoFromArchiveBuffer . mockReturnValue ( { 
500+       packageInfo : {  name : 'testpkg' ,  version : '1.0.1'  } , 
501+     }  as  any ) ; 
502+ 
503+     mockGetBundledPackageByName . mockResolvedValue ( bundledPackage ) ; 
504+     await  expect ( getPackage ( 'testpkg' ,  '1.0.1' ) ) . rejects . toThrowError ( 
505+       new  FleetError ( 'Error fetching package' ) 
506+     ) ; 
507+   } ) ; 
508+ 
509+   it ( 'should try to retrieve from cache if there is a RegistryConnectionError and no bundled package' ,  async  ( )  =>  { 
510+     mockFetchUrl . mockResolvedValue ( JSON . stringify ( [ registryPackage ] ) ) ; 
511+     mockGetResponseStreamWithSize . mockRejectedValueOnce ( 
512+       new  RegistryConnectionError ( 'Error connecting to EPR' ) 
513+     ) ; 
514+     mockStreamToBuffer . mockResolvedValue ( Buffer . from ( 'testpkg' ) ) ; 
515+     mockVerifyPackageArchiveSignature . mockResolvedValue ( 'verified' ) ; 
516+     MockArchive . unpackBufferToAssetsMap . mockReturnValue ( { 
517+       assetsMap : new  Map ( [ 
518+         [ 'test-1.0.0/LICENSE.txt' ,  Buffer . from ( '' ) ] , 
519+         [ 'test-1.0.0/changelog.yml' ,  Buffer . from ( '' ) ] , 
520+         [ 'test-1.0.0/manifest.yml' ,  Buffer . from ( '' ) ] , 
521+         [ 'test-1.0.0/docs/README.md' ,  Buffer . from ( '' ) ] , 
522+       ] ) , 
523+       paths : [ ] , 
524+       archiveIterator : { } , 
525+     }  as  any ) ; 
526+     MockArchive . getPackageInfo . mockReturnValue ( {  name : 'testpkg' ,  version : '1.0.1'  }  as  any ) ; 
527+     mockGetPackageAssetsMapCache . mockReturnValue ( { 
528+       name : 'test' , 
529+     }  as  any ) ; 
530+     mockGetBundledPackageByName . mockResolvedValue ( bundledPackage ) ; 
531+     const  result  =  await  getPackage ( 'testpkg' ,  '1.0.1' ) ; 
532+     expect ( result ) . toEqual ( { 
533+       archiveIterator : expect . any ( Object ) , 
534+       assetsMap : new  Map ( [ 
535+         [ 'test-1.0.0/LICENSE.txt' ,  Buffer . from ( '' ) ] , 
536+         [ 'test-1.0.0/changelog.yml' ,  Buffer . from ( '' ) ] , 
537+         [ 'test-1.0.0/manifest.yml' ,  Buffer . from ( '' ) ] , 
538+         [ 'test-1.0.0/docs/README.md' ,  Buffer . from ( '' ) ] , 
539+       ] ) , 
540+       packageInfo : { 
541+         name : 'testpkg' , 
542+         version : '1.0.1' , 
543+       } , 
544+       paths : [ ] , 
545+       verificationResult : undefined , 
546+     } ) ; 
547+   } ) ; 
548+ 
549+   it ( 'should falls back to bundled package if there is a RegistryConnectionError' ,  async  ( )  =>  { 
550+     mockFetchUrl . mockResolvedValue ( JSON . stringify ( [ registryPackage ] ) ) ; 
551+     mockGetResponseStreamWithSize . mockRejectedValueOnce ( 
552+       new  RegistryConnectionError ( 'Error connecting to EPR' ) 
553+     ) ; 
554+     mockStreamToBuffer . mockResolvedValue ( Buffer . from ( 'testpkg' ) ) ; 
555+     mockVerifyPackageArchiveSignature . mockResolvedValue ( 'verified' ) ; 
556+     MockArchive . unpackBufferToAssetsMap . mockReturnValue ( { 
557+       assetsMap : new  Map ( [ 
558+         [ 'test-1.0.0/LICENSE.txt' ,  Buffer . from ( '' ) ] , 
559+         [ 'test-1.0.0/changelog.yml' ,  Buffer . from ( '' ) ] , 
560+         [ 'test-1.0.0/manifest.yml' ,  Buffer . from ( '' ) ] , 
561+         [ 'test-1.0.0/docs/README.md' ,  Buffer . from ( '' ) ] , 
562+       ] ) , 
563+       paths : [ ] , 
564+       archiveIterator : { } , 
565+     }  as  any ) ; 
566+     MockArchive . getPackageInfo . mockReturnValue ( {  name : 'testpkg' ,  version : '1.0.1'  }  as  any ) ; 
567+     mockGetPackageAssetsMapCache . mockReturnValue ( new  Map ( ) ) ; 
568+     mockGetBundledPackageByName . mockResolvedValue ( bundledPackage ) ; 
569+     const  result  =  await  getPackage ( 'testpkg' ,  '1.0.1' ) ; 
570+     expect ( result ) . toEqual ( { 
571+       archiveIterator : expect . any ( Object ) , 
572+       assetsMap : new  Map ( [ 
573+         [ 'test-1.0.0/LICENSE.txt' ,  Buffer . from ( '' ) ] , 
574+         [ 'test-1.0.0/changelog.yml' ,  Buffer . from ( '' ) ] , 
575+         [ 'test-1.0.0/manifest.yml' ,  Buffer . from ( '' ) ] , 
576+         [ 'test-1.0.0/docs/README.md' ,  Buffer . from ( '' ) ] , 
577+       ] ) , 
578+       packageInfo : { 
579+         name : 'testpkg' , 
580+         version : '1.0.1' , 
581+       } , 
582+       paths : [ ] , 
583+       verificationResult : undefined , 
584+     } ) ; 
585+   } ) ; 
586+ 
587+   it ( 'should throw if there is a RegistryConnectionError and could not find bundled package nor retrieve from cache ' ,  async  ( )  =>  { 
588+     mockFetchUrl . mockResolvedValue ( JSON . stringify ( [ registryPackage ] ) ) ; 
589+     mockGetResponseStreamWithSize . mockRejectedValueOnce ( 
590+       new  RegistryConnectionError ( 'Error connecting to EPR' ) 
591+     ) ; 
592+     mockStreamToBuffer . mockResolvedValue ( Buffer . from ( 'testpkg' ) ) ; 
593+     mockVerifyPackageArchiveSignature . mockResolvedValue ( 'verified' ) ; 
594+     MockArchive . unpackBufferToAssetsMap . mockReturnValue ( { 
595+       assetsMap : new  Map ( ) , 
596+       paths : [ ] , 
597+       archiveIterator : { } , 
598+     }  as  any ) ; 
599+     MockArchive . generatePackageInfoFromArchiveBuffer . mockReturnValue ( { 
600+       packageInfo : undefined , 
601+     }  as  any ) ; 
602+ 
603+     mockGetBundledPackageByName . mockResolvedValue ( undefined ) ; 
604+     await  expect ( getPackage ( 'testpkg' ,  '1.0.1' ) ) . rejects . toThrowError ( 
605+       new  PackageNotFoundError ( '[email protected]  not found' )  606+     ) ; 
607+   } ) ; 
608+ } ) ; 
0 commit comments