-
Notifications
You must be signed in to change notification settings - Fork 8.3k
/
es_version_precheck.ts
110 lines (96 loc) · 3.14 KB
/
es_version_precheck.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { uniq } from 'lodash';
import { SemVer } from 'semver';
import {
IScopedClusterClient,
KibanaRequest,
KibanaResponseFactory,
RequestHandler,
RequestHandlerContext,
} from '@kbn/core/server';
import { versionService } from './version';
/**
* Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster.
*/
export const getAllNodeVersions = async (adminClient: IScopedClusterClient) => {
// Get the version information for all nodes in the cluster.
const response = await adminClient.asInternalUser.nodes.info({
filter_path: 'nodes.*.version',
});
const nodes = response.nodes;
const versionStrings = Object.values(nodes).map(({ version }) => version);
return uniq(versionStrings)
.sort()
.map((version) => new SemVer(version));
};
export const verifyAllMatchKibanaVersion = (allNodeVersions: SemVer[], majorVersion: number) => {
// Determine if all nodes in the cluster are running the same major version as Kibana.
const numDifferentVersion = allNodeVersions.filter(
(esNodeVersion) => esNodeVersion.major !== majorVersion
).length;
const numSameVersion = allNodeVersions.filter(
(esNodeVersion) => esNodeVersion.major === majorVersion
).length;
if (numDifferentVersion) {
return {
allNodesMatch: false,
// If Kibana is talking to nodes and none have the same major version as Kibana, they must a be of
// a higher major version.
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: RequestHandlerContext,
response: KibanaResponseFactory
) => {
const { client } = (await ctx.core).elasticsearch;
let allNodeVersions: SemVer[];
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({
// 426 means "Upgrade Required" and is used when semver compatibility is not met.
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: RequestHandler<P, Q, B>) =>
async (
ctx: RequestHandlerContext,
request: KibanaRequest<P, Q, B>,
response: KibanaResponseFactory
) => {
const errorResponse = await esVersionCheck(ctx, response);
if (errorResponse) {
return errorResponse;
}
return handler(ctx, request, response);
};