import { Client } from 'elasticsearch' ; import { ToolingLog , REPO_ROOT } from '@osd/dev-utils' ; import { createLegacyOpenSearchTestCluster , DEFAULT_SUPERUSER_PASS , opensearchTestConfig , osdTestConfig , opensearchDashboardsServerTestUser , opensearchDashboardsTestUser , setupUsers , } from '@osd/test' ; import { defaultsDeep , get } from 'lodash' ; import { resolve } from 'path' ; import { BehaviorSubject } from 'rxjs' ; import supertest from 'supertest' ; import { CoreStart } from 'src/core/server' ; import { LegacyAPICaller } from '../server/opensearch' ; import { CliArgs , Env } from '../server/config' ; import { Root } from '../server/root' ; import OsdServer from '../../legacy/server/osd_server' ; export type HttpMethod = 'delete' | 'get' | 'head' | 'post' | 'put' ; const DEFAULTS_SETTINGS = { server : { autoListen : true , port : 0 , xsrf : { disableProtection : true } , } , logging : { silent : true } , plugins : { } , migrations : { skip : true } , } ; const DEFAULT_SETTINGS_WITH_CORE_PLUGINS = { plugins : { scanDirs : [ resolve ( __dirname , '../../legacy/core_plugins' ) ] } , opensearch : { hosts : [ opensearchTestConfig . getUrl ( ) ] , username : opensearchDashboardsServerTestUser . username , password : opensearchDashboardsServerTestUser . password , } , } ; export function createRootWithSettings ( settings , cliArgs = { } ) { const env = Env . createDefault ( REPO_ROOT , { configs : [ ] , cliArgs : { dev : false , quiet : false , silent : false , watch : false , repl : false , basePath : false , runExamples : false , disableOptimizer : true , cache : true , dist : false , ... cliArgs , } , isDevClusterMaster : false , } ) ; return new Root ( { getConfig$ : ( ) => new BehaviorSubject ( defaultsDeep ( { } , settings , DEFAULTS_SETTINGS ) ) , } , env ) ; } param root param method param path export function getSupertest ( root , method , path ) { const testUserCredentials = Buffer . from ( `${ opensearchDashboardsTestUser . username }:${ opensearchDashboardsTestUser . password }` ) ; return supertest ( ( root as any ) . server . http . httpServer . server . listener ) [ method ] ( path ) . set ( 'Authorization' , `Basic ${ testUserCredentials . toString ( 'base64' ) }` ) ; } param { Object } settings returns { Root } export function createRoot ( settings = { } , cliArgs = { } ) { return createRootWithSettings ( settings , cliArgs ) ; } param { Object } settings returns { Root } export function createRootWithCorePlugins ( settings = { } ) { return createRootWithSettings ( defaultsDeep ( { } , settings , DEFAULT_SETTINGS_WITH_CORE_PLUGINS ) ) ; } param root export function getOsdServer ( root ) { return ( root as any ) . server . legacy . osdServer ; } export const request = { delete : ( root , path ) => getSupertest ( root , 'delete' , path ) , get : ( root , path ) => getSupertest ( root , 'get' , path ) , head : ( root , path ) => getSupertest ( root , 'head' , path ) , post : ( root , path ) => getSupertest ( root , 'post' , path ) , put : ( root , path ) => getSupertest ( root , 'put' , path ) , } ; export interface TestOpenSearchServer { getStartTimeout : ( ) => number ; start : ( opensearchArgs : string [ ] , opensearchEnvVars : Record < string , string > ) => Promise < void > ; stop : ( ) => Promise < void > ; cleanup : ( ) => Promise < void > ; getClient : ( ) => Client ; getCallCluster : ( ) => LegacyAPICaller ; getUrl : ( ) => string ; } export interface TestOpenSearchUtils { stop : ( ) => Promise < void > ; opensearch : TestOpenSearchServer ; hosts : string [ ] ; username : string ; password : string ; } export interface TestOpenSearchDashboardsUtils { root : Root ; coreStart : CoreStart ; osdServer : OsdServer ; stop : ( ) => Promise < void > ; } export interface TestUtils { startOpenSearch : ( ) => Promise < TestOpenSearchUtils > ; startOpenSearchDashboards : ( ) => Promise < TestOpenSearchDashboardsUtils > ; } param options prop prop export function createTestServers ( { adjustTimeout , settings = { } , } ) { if ( ! adjustTimeout ) { throw new Error ( 'adjustTimeout is required in order to avoid flaky tests' ) ; } const license = get ( settings , 'opensearch.license' , 'oss' ) ; const usersToBeAdded = get ( settings , 'users' , [ ] ) ; if ( usersToBeAdded . length > 0 ) { if ( license !== 'trial' ) { throw new Error ( 'Adding users is only supported by createTestServers when using a trial license' ) ; } } const log = new ToolingLog ( { level : 'debug' , writeTo : process . stdout , } ) ; log . indent ( 6 ) ; log . info ( 'starting opensearch' ) ; log . indent ( 4 ) ; const opensearch = createLegacyOpenSearchTestCluster ( defaultsDeep ( { } , get ( settings , 'opensearch' , { } ) , { log , license , password : license === 'trial' ? DEFAULT_SUPERUSER_PASS : undefined , } ) ) ; log . indent ( - 4 ) ; adjustTimeout ( opensearch . getStartTimeout ( ) + 100000 ) ; const osdSettings = get ( settings , 'osd' , { } ) ; return { startOpenSearch : async ( ) => { await opensearch . start ( get ( settings , 'opensearch.opensearchArgs' , [ ] ) ) ; if ( [ 'gold' , 'trial' ] . includes ( license ) ) { await setupUsers ( { log , opensearchPort : opensearchTestConfig . getUrlParts ( ) . port , updates : [ ... usersToBeAdded , opensearchTestConfig . getUrlParts ( ) , osdTestConfig . getUrlParts ( ) , ] , } ) ; osdSettings . opensearch = { hosts : [ opensearchTestConfig . getUrl ( ) ] , username : opensearchDashboardsServerTestUser . username , password : opensearchDashboardsServerTestUser . password , } ; } return { stop : async ( ) => await opensearch . cleanup ( ) , opensearch , hosts : [ opensearchTestConfig . getUrl ( ) ] , username : opensearchDashboardsServerTestUser . username , password : opensearchDashboardsServerTestUser . password , } ; } , startOpenSearchDashboards : async ( ) => { const root = createRootWithCorePlugins ( osdSettings ) ; await root . setup ( ) ; const coreStart = await root . start ( ) ; const osdServer = getOsdServer ( root ) ; return { root , osdServer , coreStart , stop : async ( ) => await root . shutdown ( ) , } ; } , } ; }