import { uniq } from 'lodash' ; import { SemVer } from 'semver' ; import { IScopedClusterClient , KibanaRequest , KibanaResponseFactory , RequestHandler , RequestHandlerContext , } from 'src/core/server' ; import { versionService } from './version' ; interface Nodes { nodes : { [ nodeId ] : { version : string ; } ; } ; } /**
 * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster.
 */ export const getAllNodeVersions = async ( adminClient ) => { const response = await adminClient . asInternalUser . nodes . info < Nodes > ( { filter_path : 'nodes.*.version' , } ) ; const nodes = response . body . nodes ; const versionStrings = Object . values ( nodes ) . map ( ( { version } ) => version ) ; return uniq ( versionStrings ) . sort ( ) . map ( ( version ) => new SemVer ( version ) ) ; } ; export const verifyAllMatchKibanaVersion = ( allNodeVersions , majorVersion ) => { const numDifferentVersion = allNodeVersions . filter ( ( esNodeVersion ) => esNodeVersion . major !== majorVersion ) . length ; const numSameVersion = allNodeVersions . filter ( ( esNodeVersion ) => esNodeVersion . major === majorVersion ) . length ; if ( numDifferentVersion ) { return { allNodesMatch : false , allNodesUpgraded : numSameVersion === 0 , } ; } return { allNodesMatch : true , allNodesUpgraded : false , } ; } ; /**
 * This is intended as controller/handler level code so it knows about HTTP
 */ export const esVersionCheck = async ( ctx , response ) => { const { client } = ctx . core . elasticsearch ; let allNodeVersions ; try { allNodeVersions = await getAllNodeVersions ( client ) ; } catch ( e ) { if ( e . statusCode === 403 ) { return response . forbidden ( { body : e . message } ) ; } throw e ; } const majorVersion = versionService . getMajorVersion ( ) ; const result = verifyAllMatchKibanaVersion ( allNodeVersions , majorVersion ) ; if ( ! result . allNodesMatch ) { return response . customError ( { statusCode : 426 , body : { message : 'There are some nodes running a different version of Elasticsearch' , attributes : { allNodesUpgraded : result . allNodesUpgraded , } , } , } ) ; } } ; export const versionCheckHandlerWrapper = < P , Q , B > ( handler ) => async ( ctx , request , response ) => { const errorResponse = await esVersionCheck ( ctx , response ) ; if ( errorResponse ) { return errorResponse ; } return handler ( ctx , request , response ) ; } ;