import expect from '@kbn/expect' ; import { FtrProviderContext } from '../../../ftr_provider_context' ; import { registerEsHelpers , SlmPolicy } from './lib' ; import { SnapshotDetails } from '../../../../../plugins/snapshot_restore/common/types' ; const REPO_NAME_1 = 'test_repo_1' ; const REPO_NAME_2 = 'test_another_repo_2' ; const REPO_PATH_1 = '/tmp/repo_1' ; const REPO_PATH_2 = '/tmp/repo_2' ; const POLICY_NAME_1 = 'test_policy_1' ; const POLICY_NAME_2 = 'test_another_policy_2' ; const POLICY_SNAPSHOT_NAME_1 = 'backup_snapshot' ; const POLICY_SNAPSHOT_NAME_2 = 'a_snapshot' ; const BATCH_SIZE_1 = 3 ; const BATCH_SIZE_2 = 5 ; const BATCH_SNAPSHOT_NAME_1 = 'another_snapshot' ; const BATCH_SNAPSHOT_NAME_2 = 'xyz_another_snapshot' ; const SNAPSHOT_COUNT = BATCH_SIZE_1 + BATCH_SIZE_2 + 2 ; const PAGE_INDEX = 0 ; const PAGE_SIZE = 20 ; const SORT_FIELD = 'startTimeInMillis' ; const SORT_DIRECTION = 'desc' ; interface ApiParams { pageIndex ? : number ; pageSize ? : number ; sortField ? : string ; sortDirection ? : string ; searchField ? : string ; searchValue ? : string ; searchMatch ? : string ; searchOperator ? : string ; } const getApiPath = ( { pageIndex , pageSize , sortField , sortDirection , searchField , searchValue , searchMatch , searchOperator , } ) : string => { let path = `/api/snapshot_restore/snapshots?sortField=${ sortField ?? SORT_FIELD }&sortDirection=${ sortDirection ?? SORT_DIRECTION }&pageIndex=${ pageIndex ?? PAGE_INDEX }&pageSize=${ pageSize ?? PAGE_SIZE }` ; if ( searchField && searchValue && searchMatch && searchOperator ) { path = `${ path }&searchField=${ searchField }&searchValue=${ searchValue }&searchMatch=${ searchMatch }&searchOperator=${ searchOperator }` ; } return path ; } ; const getPolicyBody = ( policy ) : SlmPolicy => { return { policyName : 'default_policy' , name : 'default_snapshot' , schedule : '0 30 1 * * ?' , repository : 'default_repo' , isManagedPolicy : false , config : { indices : [ 'default_index' ] , ignoreUnavailable : true , } , ... policy , } ; } ; export default function ( { getService } ) { const supertest = getService ( 'supertest' ) ; const { createSnapshot , createRepository , createPolicy , executePolicy , cleanupPolicies , deleteSnapshots , } = registerEsHelpers ( getService ) ; describe ( 'Snapshots' , function ( ) { this . tags ( [ 'skipCloud' ] ) ; let snapshotName1 ; let snapshotName2 ; before ( async ( ) => { try { await createRepository ( REPO_NAME_1 , REPO_PATH_1 ) ; await createRepository ( REPO_NAME_2 , REPO_PATH_2 ) ; await createPolicy ( getPolicyBody ( { policyName : POLICY_NAME_1 , repository : REPO_NAME_1 , name : POLICY_SNAPSHOT_NAME_1 , } ) , true ) ; await createPolicy ( getPolicyBody ( { policyName : POLICY_NAME_2 , repository : REPO_NAME_1 , name : POLICY_SNAPSHOT_NAME_2 , } ) , true ) ; ( { snapshot_name : snapshotName1 } = await executePolicy ( POLICY_NAME_1 ) ) ; await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ; ( { snapshot_name : snapshotName2 } = await executePolicy ( POLICY_NAME_2 ) ) ; for ( let i = 0 ; i < BATCH_SIZE_1 ; i ++ ) { await createSnapshot ( `${ BATCH_SNAPSHOT_NAME_1 }_${ i }` , REPO_NAME_1 ) ; } for ( let i = 0 ; i < BATCH_SIZE_2 ; i ++ ) { await createSnapshot ( `${ BATCH_SNAPSHOT_NAME_2 }_${ i }` , REPO_NAME_2 ) ; } } catch ( err ) { console . log ( '[Setup error] Error creating snapshots' ) ; throw err ; } } ) ; after ( async ( ) => { await cleanupPolicies ( ) ; await deleteSnapshots ( REPO_NAME_1 ) ; await deleteSnapshots ( REPO_NAME_2 ) ; } ) ; describe ( 'pagination' , ( ) => { it ( 'returns pageSize number of snapshots' , async ( ) => { const pageSize = 7 ; const { body : { total , snapshots } , } = await supertest . get ( getApiPath ( { pageSize , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( total ) . to . eql ( SNAPSHOT_COUNT ) ; expect ( snapshots . length ) . to . eql ( pageSize ) ; } ) ; it ( 'returns next page of snapshots' , async ( ) => { const pageSize = 3 ; let pageIndex = 0 ; const { body : { snapshots : firstPageSnapshots } , } = await supertest . get ( getApiPath ( { pageIndex , pageSize , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const firstPageSnapshotName = firstPageSnapshots [ 0 ] . snapshot ; expect ( firstPageSnapshots . length ) . to . eql ( pageSize ) ; pageIndex = 1 ; const { body : { snapshots : secondPageSnapshots } , } = await supertest . get ( getApiPath ( { pageIndex , pageSize , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const secondPageSnapshotName = secondPageSnapshots [ 0 ] . snapshot ; expect ( secondPageSnapshots . length ) . to . eql ( pageSize ) ; expect ( secondPageSnapshotName ) . to . not . eql ( firstPageSnapshotName ) ; } ) ; } ) ; describe ( 'sorting' , ( ) => { it ( 'sorts by snapshot name (asc)' , async ( ) => { const { body : { snapshots } , } = await supertest . get ( getApiPath ( { sortField : 'snapshot' , sortDirection : 'asc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const snapshotName = snapshots [ 0 ] . snapshot ; expect ( snapshotName ) . to . eql ( snapshotName2 ) ; } ) ; it ( 'sorts by snapshot name (desc)' , async ( ) => { const { body : { snapshots } , } = await supertest . get ( getApiPath ( { sortField : 'snapshot' , sortDirection : 'desc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const snapshotName = snapshots [ 0 ] . snapshot ; expect ( snapshotName ) . to . eql ( 'xyz_another_snapshot_4' ) ; } ) ; it ( 'sorts by repository name (asc)' , async ( ) => { const { body : { snapshots } , } = await supertest . get ( getApiPath ( { sortField : 'repository' , sortDirection : 'asc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const repositoryName = snapshots [ 0 ] . repository ; expect ( repositoryName ) . to . eql ( REPO_NAME_2 ) ; } ) ; it ( 'sorts by repository name (desc)' , async ( ) => { const { body : { snapshots } , } = await supertest . get ( getApiPath ( { sortField : 'repository' , sortDirection : 'desc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const repositoryName = snapshots [ 0 ] . repository ; expect ( repositoryName ) . to . eql ( REPO_NAME_1 ) ; } ) ; it ( 'sorts by startTimeInMillis (asc)' , async ( ) => { const { body : { snapshots } , } = await supertest . get ( getApiPath ( { sortField : 'startTimeInMillis' , sortDirection : 'asc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const snapshotName = snapshots [ 0 ] . snapshot ; expect ( snapshotName ) . to . eql ( snapshotName1 ) ; } ) ; it ( 'sorts by startTimeInMillis (desc)' , async ( ) => { const { body : { snapshots } , } = await supertest . get ( getApiPath ( { sortField : 'startTimeInMillis' , sortDirection : 'desc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; const snapshotName = snapshots [ 0 ] . snapshot ; expect ( snapshotName ) . to . eql ( 'xyz_another_snapshot_4' ) ; } ) ; const sortFields = [ 'indices' , 'durationInMillis' , 'shards.total' , 'shards.failed' ] ; sortFields . forEach ( ( sortField ) => { it ( `allows sorting by ${ sortField } (asc)` , async ( ) => { await supertest . get ( getApiPath ( { sortField , sortDirection : 'asc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) . expect ( 200 ) ; } ) ; it ( `allows sorting by ${ sortField } (desc)` , async ( ) => { await supertest . get ( getApiPath ( { sortField , sortDirection : 'desc' , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) . expect ( 200 ) ; } ) ; } ) ; } ) ; describe ( 'search' , ( ) => { describe ( 'snapshot name' , ( ) => { it ( 'exact match' , async ( ) => { const searchField = 'snapshot' ; const searchValue = 'another_snapshot_2' ; const searchMatch = 'must' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( 1 ) ; expect ( snapshots [ 0 ] . snapshot ) . to . eql ( 'another_snapshot_2' ) ; } ) ; it ( 'partial match' , async ( ) => { const searchField = 'snapshot' ; const searchValue = 'another' ; const searchMatch = 'must' ; const searchOperator = 'eq' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( BATCH_SIZE_1 + BATCH_SIZE_2 ) ; const snapshotNamesContainSearch = snapshots . every ( ( snapshot ) => snapshot . snapshot . includes ( 'another' ) ) ; expect ( snapshotNamesContainSearch ) . to . eql ( true ) ; } ) ; it ( 'excluding search with exact match' , async ( ) => { const searchField = 'snapshot' ; const searchValue = 'another_snapshot_2' ; const searchMatch = 'must_not' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( SNAPSHOT_COUNT - 1 ) ; const snapshotIsExcluded = snapshots . every ( ( snapshot ) => snapshot . snapshot !== 'another_snapshot_2' ) ; expect ( snapshotIsExcluded ) . to . eql ( true ) ; } ) ; it ( 'excluding search with partial match' , async ( ) => { const searchField = 'snapshot' ; const searchValue = 'another' ; const searchMatch = 'must_not' ; const searchOperator = 'eq' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( SNAPSHOT_COUNT - BATCH_SIZE_1 - BATCH_SIZE_2 ) ; const snapshotsAreExcluded = snapshots . every ( ( snapshot ) => ! snapshot . snapshot . includes ( 'another' ) ) ; expect ( snapshotsAreExcluded ) . to . eql ( true ) ; } ) ; } ) ; describe ( 'repository name' , ( ) => { it ( 'search for non-existent repository returns an empty snapshot array' , async ( ) => { const searchField = 'repository' ; const searchValue = 'non-existent' ; const searchMatch = 'must' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( 0 ) ; } ) ; it ( 'exact match' , async ( ) => { const searchField = 'repository' ; const searchValue = REPO_NAME_1 ; const searchMatch = 'must' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( BATCH_SIZE_1 + 2 ) ; const repositoryNameMatches = snapshots . every ( ( snapshot ) => snapshot . repository === REPO_NAME_1 ) ; expect ( repositoryNameMatches ) . to . eql ( true ) ; } ) ; it ( 'partial match' , async ( ) => { const searchField = 'repository' ; const searchValue = 'another' ; const searchMatch = 'must' ; const searchOperator = 'eq' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( BATCH_SIZE_2 ) ; const repositoryNameMatches = snapshots . every ( ( snapshot ) => snapshot . repository . includes ( 'another' ) ) ; expect ( repositoryNameMatches ) . to . eql ( true ) ; } ) ; it ( 'excluding search with exact match' , async ( ) => { const searchField = 'repository' ; const searchValue = REPO_NAME_1 ; const searchMatch = 'must_not' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( BATCH_SIZE_2 ) ; const repositoryNameMatches = snapshots . every ( ( snapshot ) => snapshot . repository !== REPO_NAME_1 ) ; expect ( repositoryNameMatches ) . to . eql ( true ) ; } ) ; it ( 'excluding search with partial match' , async ( ) => { const searchField = 'repository' ; const searchValue = 'test' ; const searchMatch = 'must_not' ; const searchOperator = 'eq' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( 0 ) ; } ) ; } ) ; describe ( 'policy name' , ( ) => { it ( 'search for non-existent policy returns an empty snapshot array' , async ( ) => { const searchField = 'policyName' ; const searchValue = 'non-existent' ; const searchMatch = 'must' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( 0 ) ; } ) ; it ( 'exact match' , async ( ) => { const searchField = 'policyName' ; const searchValue = POLICY_NAME_1 ; const searchMatch = 'must' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( 1 ) ; expect ( snapshots [ 0 ] . policyName ) . to . eql ( POLICY_NAME_1 ) ; } ) ; it ( 'partial match' , async ( ) => { const searchField = 'policyName' ; const searchValue = 'another' ; const searchMatch = 'must' ; const searchOperator = 'eq' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( 1 ) ; const policyNameMatches = snapshots . every ( ( snapshot ) => snapshot . policyName ! . includes ( 'another' ) ) ; expect ( policyNameMatches ) . to . eql ( true ) ; } ) ; it ( 'excluding search with exact match' , async ( ) => { const searchField = 'policyName' ; const searchValue = POLICY_NAME_1 ; const searchMatch = 'must_not' ; const searchOperator = 'exact' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( SNAPSHOT_COUNT - 1 ) ; const snapshotsExcluded = snapshots . every ( ( snapshot ) => ( snapshot . policyName ?? '' ) !== POLICY_NAME_1 ) ; expect ( snapshotsExcluded ) . to . eql ( true ) ; } ) ; it ( 'excluding search with partial match' , async ( ) => { const searchField = 'policyName' ; const searchValue = 'another' ; const searchMatch = 'must_not' ; const searchOperator = 'eq' ; const { body : { snapshots } , } = await supertest . get ( getApiPath ( { searchField , searchValue , searchMatch , searchOperator , } ) ) . set ( 'kbn-xsrf' , 'xxx' ) . send ( ) ; expect ( snapshots . length ) . to . eql ( SNAPSHOT_COUNT - 1 ) ; const snapshotsExcluded = snapshots . every ( ( snapshot ) => ! ( snapshot . policyName ?? '' ) . includes ( 'another' ) ) ; expect ( snapshotsExcluded ) . to . eql ( true ) ; } ) ; } ) ; } ) ; } ) ; }