diff --git a/src/core_plugins/elasticsearch/lib/__tests__/check_for_tribe.js b/src/core_plugins/elasticsearch/lib/__tests__/check_for_tribe.js new file mode 100644 index 0000000000000..1ad6f1f814928 --- /dev/null +++ b/src/core_plugins/elasticsearch/lib/__tests__/check_for_tribe.js @@ -0,0 +1,44 @@ +import expect from 'expect.js'; +import { noop } from 'lodash'; +import sinon from 'sinon'; + +import checkForTribe from '../check_for_tribe'; + +describe('plugins/elasticsearch checkForTribe', () => { + const sandbox = sinon.sandbox.create(); + afterEach(() => sandbox.restore()); + + const stubClient = (nodesInfoResp = { nodes: {} }) => ({ + nodes: { + info: sandbox.spy(async () => await nodesInfoResp) + } + }); + + it('fetches the local node stats of the node that the elasticsearch client is connected to', async () => { + const client = stubClient(); + await checkForTribe(client); + sinon.assert.calledOnce(client.nodes.info); + }); + + it('throws a SetupError when the node info contains tribe settings', async () => { + const nodeInfo = { + nodes: { + __nodeId__: { + settings: { + tribe: { + t1: {}, + t2: {}, + } + } + } + } + }; + + try { + await checkForTribe(stubClient(nodeInfo)); + throw new Error('checkForTribe() should have thrown'); + } catch (err) { + expect(err).to.be.a(Error); + } + }); +}); diff --git a/src/core_plugins/elasticsearch/lib/__tests__/health_check.js b/src/core_plugins/elasticsearch/lib/__tests__/health_check.js index 58382d2b68526..79c87a5a5569e 100644 --- a/src/core_plugins/elasticsearch/lib/__tests__/health_check.js +++ b/src/core_plugins/elasticsearch/lib/__tests__/health_check.js @@ -86,7 +86,7 @@ describe('plugins/elasticsearch', () => { sinon.assert.calledOnce(plugin.status.yellow); expect(plugin.status.yellow.args[0][0]).to.be('Waiting for Elasticsearch'); sinon.assert.calledOnce(client.ping); - sinon.assert.calledOnce(client.nodes.info); + sinon.assert.calledTwice(client.nodes.info); sinon.assert.calledOnce(client.cluster.health); sinon.assert.calledOnce(plugin.status.green); expect(plugin.status.green.args[0][0]).to.be('Kibana index ready'); @@ -106,7 +106,7 @@ describe('plugins/elasticsearch', () => { `Unable to connect to Elasticsearch at ${esUrl}.` ); sinon.assert.calledTwice(client.ping); - sinon.assert.calledOnce(client.nodes.info); + sinon.assert.calledTwice(client.nodes.info); sinon.assert.calledOnce(client.cluster.health); sinon.assert.calledOnce(plugin.status.green); expect(plugin.status.green.args[0][0]).to.be('Kibana index ready'); @@ -126,7 +126,7 @@ describe('plugins/elasticsearch', () => { 'Elasticsearch is still initializing the kibana index.' ); sinon.assert.calledOnce(client.ping); - sinon.assert.calledOnce(client.nodes.info); + sinon.assert.calledTwice(client.nodes.info); sinon.assert.calledTwice(client.cluster.health); sinon.assert.calledOnce(plugin.status.green); expect(plugin.status.green.args[0][0]).to.be('Kibana index ready'); @@ -145,7 +145,7 @@ describe('plugins/elasticsearch', () => { expect(plugin.status.yellow.args[1][0]).to.be('No existing Kibana index found'); sinon.assert.calledOnce(client.ping); sinon.assert.calledOnce(client.indices.create); - sinon.assert.calledOnce(client.nodes.info); + sinon.assert.calledTwice(client.nodes.info); sinon.assert.calledTwice(client.cluster.health); }); }); diff --git a/src/core_plugins/elasticsearch/lib/check_es_version.js b/src/core_plugins/elasticsearch/lib/check_es_version.js index 463f512666ef1..8c8f6f9054b49 100644 --- a/src/core_plugins/elasticsearch/lib/check_es_version.js +++ b/src/core_plugins/elasticsearch/lib/check_es_version.js @@ -9,12 +9,12 @@ import semver from 'semver'; import isEsCompatibleWithKibana from './is_es_compatible_with_kibana'; /** - * tracks the node descriptions that get logged in warnings so - * that we don't spam the log with the same message over and over. + * tracks the node descriptions that get logged in warnings so + * that we don't spam the log with the same message over and over. * - * There are situations, like in testing or multi-tenancy, where - * the server argument changes, so we must track the previous - * node warnings per server + * There are situations, like in testing or multi-tenancy, where + * the server argument changes, so we must track the previous + * node warnings per server */ const lastWarnedNodesForServer = new WeakMap(); @@ -23,7 +23,13 @@ module.exports = function checkEsVersion(server, kibanaVersion) { const client = server.plugins.elasticsearch.client; - return client.nodes.info() + return client.nodes.info({ + filterPath: [ + 'nodes.*.version', + 'nodes.*.http.publish_address', + 'nodes.*.ip', + ] + }) .then(function (info) { // Aggregate incompatible ES nodes. const incompatibleNodes = []; diff --git a/src/core_plugins/elasticsearch/lib/check_for_tribe.js b/src/core_plugins/elasticsearch/lib/check_for_tribe.js new file mode 100644 index 0000000000000..86897dd866a14 --- /dev/null +++ b/src/core_plugins/elasticsearch/lib/check_for_tribe.js @@ -0,0 +1,18 @@ +import { get } from 'lodash'; + +export default function checkForTribe(client) { + return client.nodes.info({ + nodeId: '_local', + filterPath: 'nodes.*.settings.tribe' + }) + .then(function (info) { + const nodeId = Object.keys(info.nodes || {})[0]; + const tribeSettings = get(info, ['nodes', nodeId, 'settings', 'tribe']); + + if (tribeSettings) { + throw new Error('Kibana does not support using tribe nodes as the primary elasticsearch connection.'); + } + + return true; + }); +}; diff --git a/src/core_plugins/elasticsearch/lib/health_check.js b/src/core_plugins/elasticsearch/lib/health_check.js index 4f1555893d871..99560396976ce 100644 --- a/src/core_plugins/elasticsearch/lib/health_check.js +++ b/src/core_plugins/elasticsearch/lib/health_check.js @@ -6,6 +6,7 @@ import migrateConfig from './migrate_config'; import createKibanaIndex from './create_kibana_index'; import checkEsVersion from './check_es_version'; import kibanaVersion from './kibana_version'; +import checkForTribe from './check_for_tribe'; const NoConnections = elasticsearch.errors.NoConnections; import util from 'util'; @@ -87,7 +88,13 @@ module.exports = function (plugin, server) { function check() { return waitForPong() - .then(() => checkEsVersion(server, kibanaVersion.get())) + .then(() => { + // execute version and tribe checks in parallel + // but always report the version check result first + const versionPromise = checkEsVersion(server, kibanaVersion.get()); + const tribePromise = checkForTribe(client); + return versionPromise.then(() => tribePromise); + }) .then(waitForShards) .then(setGreenStatus) .then(_.partial(migrateConfig, server))