mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Adding tests for the elasticsearch plugin
This commit is contained in:
parent
259b6f7910
commit
1d7749f3df
23 changed files with 1386 additions and 365 deletions
0
src/hapi/bin/kibana.js
Normal file → Executable file
0
src/hapi/bin/kibana.js
Normal file → Executable file
|
@ -55,6 +55,7 @@ module.exports = Joi.object({
|
|||
cert: Joi.string(),
|
||||
key: Joi.string()
|
||||
}).default(),
|
||||
minimumVerison: Joi.string().default('1.4.4')
|
||||
}).default(),
|
||||
logging: Joi.object({
|
||||
quiet: Joi.boolean().default(false),
|
||||
|
|
|
@ -16,8 +16,6 @@ module.exports = new kibana.Plugin({
|
|||
// Expose the client to the server
|
||||
exposeClient(server);
|
||||
|
||||
// Set up the health check service
|
||||
healthCheck(this, server);
|
||||
|
||||
createProxy(server, 'GET', '/elasticsearch/{paths*}');
|
||||
createProxy(server, 'POST', '/elasticsearch/_mget');
|
||||
|
@ -42,5 +40,8 @@ module.exports = new kibana.Plugin({
|
|||
}
|
||||
);
|
||||
|
||||
// Set up the health check service and start it.
|
||||
healthCheck(this, server).start();
|
||||
|
||||
}
|
||||
});
|
||||
|
|
38
src/hapi/plugins/elasticsearch/lib/check_es_version.js
Normal file
38
src/hapi/plugins/elasticsearch/lib/check_es_version.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
var _ = require('lodash');
|
||||
_.mixin(require('lodash-deep'));
|
||||
var esBool = require('./es_bool');
|
||||
var versionMath = require('./version_math');
|
||||
var SetupError = require('./setup_error');
|
||||
module.exports = function (server) {
|
||||
return function () {
|
||||
var client = server.plugins.elasticsearch.client;
|
||||
var minimumElasticsearchVersion = server.config().get('elasticsearch.minimumVerison');
|
||||
return client.nodes.info()
|
||||
.then(function (info) {
|
||||
var badNodes = _.filter(info.nodes, function (node) {
|
||||
// remove client nodes (Logstash)
|
||||
var isClient = _.deepGet(node, 'attributes.client');
|
||||
if (isClient != null && esBool(isClient) === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove nodes that are gte the min version
|
||||
var v = node.version.split('-')[0];
|
||||
return !versionMath.gte(minimumElasticsearchVersion, v);
|
||||
});
|
||||
|
||||
if (!badNodes.length) return true;
|
||||
|
||||
var badNodeNames = badNodes.map(function (node) {
|
||||
return 'Elasticsearch v' + node.version + ' @ ' + node.http_address + ' (' + node.ip + ')';
|
||||
});
|
||||
|
||||
var message = 'This version of Kibana requires Elasticsearch ' +
|
||||
minimumElasticsearchVersion + ' or higher on all nodes. ' +
|
||||
'I found the following incompatible nodes in your cluster: ' +
|
||||
badNodeNames.join(',');
|
||||
server.plugins.elasticsearch.status.red(message);
|
||||
throw new SetupError(server, message);
|
||||
});
|
||||
};
|
||||
};
|
40
src/hapi/plugins/elasticsearch/lib/create_kibana_index.js
Normal file
40
src/hapi/plugins/elasticsearch/lib/create_kibana_index.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
var SetupError = require('./setup_error');
|
||||
var format = require('util').format;
|
||||
module.exports = function (server) {
|
||||
var client = server.plugins.elasticsearch.client;
|
||||
var index = server.config().get('kibana.index');
|
||||
|
||||
function handleError(message) {
|
||||
return function (err) {
|
||||
throw new SetupError(server, message, err);
|
||||
};
|
||||
}
|
||||
|
||||
return client.indices.create({
|
||||
index: index,
|
||||
body: {
|
||||
settings: {
|
||||
number_of_shards: 1,
|
||||
number_of_replicas: 1
|
||||
},
|
||||
mappings: {
|
||||
config: {
|
||||
properties: {
|
||||
buildNum: {
|
||||
type: 'string',
|
||||
index: 'not_analyzed'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(handleError('Unable to create Kibana index "<%= kibana.index %>"'))
|
||||
.then(function () {
|
||||
return client.cluster.health({
|
||||
waitForStatus: 'yellow',
|
||||
index: index
|
||||
})
|
||||
.catch(handleError('Waiting for Kibana index "<%= kibana.index %>" to come online failed.'));
|
||||
});
|
||||
};
|
17
src/hapi/plugins/elasticsearch/lib/es_bool.js
Normal file
17
src/hapi/plugins/elasticsearch/lib/es_bool.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
var map = {
|
||||
'false': false,
|
||||
'off': false,
|
||||
'no': false,
|
||||
'0': false,
|
||||
'true': true,
|
||||
'on': true,
|
||||
'yes': true,
|
||||
'1': true
|
||||
};
|
||||
module.exports = function (str) {
|
||||
var bool = map[String(str)];
|
||||
if (typeof bool !== 'boolean') {
|
||||
throw new TypeError('"' + str + '" does not map to an esBool');
|
||||
}
|
||||
return bool;
|
||||
};
|
|
@ -1,6 +1,9 @@
|
|||
var Promise = require('bluebird');
|
||||
var elasticsearch = require('elasticsearch');
|
||||
var exposeClient = require('./expose_client');
|
||||
var migrateConfig = require('./migrate_config');
|
||||
var createKibanaIndex = require('./create_kibana_index');
|
||||
var checkEsVersion = require('./check_es_version');
|
||||
var NoConnections = elasticsearch.errors.NoConnections;
|
||||
var util = require('util');
|
||||
var format = util.format;
|
||||
|
@ -30,8 +33,8 @@ module.exports = function (plugin, server) {
|
|||
// if "timed_out" === true then elasticsearch could not
|
||||
// find any idices matching our filter within 5 seconds
|
||||
if (resp.timed_out) {
|
||||
plugin.status.red('No existing Kibana index found');
|
||||
return;
|
||||
plugin.status.yellow('No existing Kibana index found');
|
||||
return createKibanaIndex(server);
|
||||
}
|
||||
|
||||
// If status === "red" that means that index(es) were found
|
||||
|
@ -46,17 +49,42 @@ module.exports = function (plugin, server) {
|
|||
});
|
||||
}
|
||||
|
||||
var running = false;
|
||||
|
||||
function runHealthCheck() {
|
||||
setTimeout(healthCheck, 2500);
|
||||
if (running) {
|
||||
setTimeout(function () {
|
||||
healthCheck()
|
||||
.then(runHealthCheck)
|
||||
.catch(function (err) {
|
||||
server.log('error', err);
|
||||
runHealthCheck();
|
||||
});
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
|
||||
function healthCheck() {
|
||||
waitForPong()
|
||||
return waitForPong()
|
||||
.then(checkEsVersion(server))
|
||||
.then(waitForShards)
|
||||
.then(runHealthCheck)
|
||||
.catch(runHealthCheck);
|
||||
.then(migrateConfig(server));
|
||||
}
|
||||
|
||||
healthCheck();
|
||||
return {
|
||||
isRunning: function () {
|
||||
return running;
|
||||
},
|
||||
run: function () {
|
||||
return healthCheck();
|
||||
},
|
||||
start: function () {
|
||||
running = true;
|
||||
return healthCheck().then(runHealthCheck, runHealthCheck);
|
||||
},
|
||||
stop: function () {
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
|
33
src/hapi/plugins/elasticsearch/lib/is_upgradeable.js
Normal file
33
src/hapi/plugins/elasticsearch/lib/is_upgradeable.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
var semver = require('semver');
|
||||
var rcVersionRegex = /(\d+\.\d+\.\d+)\-rc(\d+)/i;
|
||||
|
||||
module.exports = function (server, doc) {
|
||||
var config = server.config();
|
||||
if (/beta|snapshot/i.test(doc._id)) return false;
|
||||
if (!doc._id) return false;
|
||||
if (doc._id === config.get('kibana.package.version')) return false;
|
||||
|
||||
var packageRcRelease = Infinity;
|
||||
var rcRelease = Infinity;
|
||||
var packageVersion = config.get('kibana.package.version');
|
||||
var version = doc._id;
|
||||
var matches = doc._id.match(rcVersionRegex);
|
||||
var packageMatches = config.get('kibana.package.version').match(rcVersionRegex);
|
||||
|
||||
if (matches) {
|
||||
version = matches[1];
|
||||
rcRelease = parseInt(matches[2], 10);
|
||||
}
|
||||
|
||||
if (packageMatches) {
|
||||
packageVersion = packageMatches[1];
|
||||
packageRcRelease = parseInt(packageMatches[2], 10);
|
||||
}
|
||||
|
||||
try {
|
||||
if (semver.gte(version, packageVersion) && rcRelease >= packageRcRelease) return false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
29
src/hapi/plugins/elasticsearch/lib/migrate_config.js
Normal file
29
src/hapi/plugins/elasticsearch/lib/migrate_config.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
var upgrade = require('./upgrade_config');
|
||||
|
||||
module.exports = function (server) {
|
||||
return function () {
|
||||
var config = server.config();
|
||||
var client = server.plugins.elasticsearch.client;
|
||||
var options = {
|
||||
index: config.get('kibana.index'),
|
||||
type: 'config',
|
||||
body: {
|
||||
size: 1000,
|
||||
sort: [ { buildNum: { order: 'desc' } } ],
|
||||
query: {
|
||||
filtered: {
|
||||
filter: {
|
||||
bool: {
|
||||
must_not: [ { query: { match: { _id: '@@version' } } } ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return client.search(options).then(upgrade(server));
|
||||
};
|
||||
};
|
||||
|
||||
|
18
src/hapi/plugins/elasticsearch/lib/setup_error.js
Normal file
18
src/hapi/plugins/elasticsearch/lib/setup_error.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
var _ = require('lodash');
|
||||
var util = require('util');
|
||||
|
||||
function SetupError(server, template, err) {
|
||||
var config = server.config().get();
|
||||
// don't override other setup errors
|
||||
if (err && err instanceof SetupError) return err;
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
this.name = this.constructor.name;
|
||||
this.message = _.template(template, config);
|
||||
if (err) {
|
||||
this.origError = err;
|
||||
if (err.stack) this.stack = err.stack;
|
||||
}
|
||||
}
|
||||
util.inherits(SetupError, Error);
|
||||
module.exports = SetupError;
|
||||
|
42
src/hapi/plugins/elasticsearch/lib/upgrade_config.js
Normal file
42
src/hapi/plugins/elasticsearch/lib/upgrade_config.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
var Promise = require('bluebird');
|
||||
var isUpgradeable = require('./is_upgradeable');
|
||||
var _ = require('lodash');
|
||||
var format = require('util').format;
|
||||
module.exports = function (server) {
|
||||
var client = server.plugins.elasticsearch.client;
|
||||
var config = server.config();
|
||||
return function (response) {
|
||||
var newConfig = {};
|
||||
// Check to see if there are any doc. If not then we can assume
|
||||
// nothing needs to be done
|
||||
if (response.hits.hits.length === 0) return Promise.resolve();
|
||||
|
||||
// if we already have a the current version in the index then we need to stop
|
||||
if (_.find(response.hits.hits, { _id: config.get('kibana.package.version') })) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Look for upgradeable configs. If none of them are upgradeable
|
||||
// then resolve with null.
|
||||
var body = _.find(response.hits.hits, isUpgradeable.bind(null, server));
|
||||
if (!body) return Promise.resolve();
|
||||
|
||||
|
||||
// if the build number is still the template string (which it wil be in development)
|
||||
// then we need to set it to the max interger. Otherwise we will set it to the build num
|
||||
body._source.buildNum = Math.pow(2, 53) - 1;
|
||||
if (!/^@@/.test(config.get('kibana.buildNum'))) {
|
||||
body._source.buildNum = parseInt(config.get('kibana.buildNum'), 10);
|
||||
}
|
||||
|
||||
var logMsg = format('[ elasticsearch ] Upgrade config from %s to %s', body._id, config.get('kibana.package.version'));
|
||||
server.log('plugin', logMsg);
|
||||
return client.create({
|
||||
index: config.get('kibana.index'),
|
||||
type: 'config',
|
||||
body: body._source,
|
||||
id: config.get('kibana.package.version')
|
||||
});
|
||||
};
|
||||
};
|
||||
|
139
src/hapi/plugins/elasticsearch/lib/version_math.js
Normal file
139
src/hapi/plugins/elasticsearch/lib/version_math.js
Normal file
|
@ -0,0 +1,139 @@
|
|||
var _ = require('lodash');
|
||||
|
||||
function VersionMathException(message) {
|
||||
this.message = message;
|
||||
this.name = 'VersionMathException';
|
||||
}
|
||||
|
||||
// Determine if a specific version meets the minimum requirement
|
||||
var compare = function (required, installed) {
|
||||
if (_.isUndefined(installed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!required || !installed) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var a = installed.split('.');
|
||||
var b = required.split('.');
|
||||
var i;
|
||||
|
||||
// leave suffixes as is ("RC1 or -SNAPSHOT")
|
||||
for (i = 0; i < Math.min(a.length, 3); ++i) {
|
||||
a[i] = Number(a[i]);
|
||||
}
|
||||
for (i = 0; i < Math.min(b.length, 3); ++i) {
|
||||
b[i] = Number(b[i]);
|
||||
}
|
||||
if (a.length === 2) {
|
||||
a[2] = 0;
|
||||
}
|
||||
|
||||
if (a[0] > b[0]) { return true; }
|
||||
if (a[0] < b[0]) { return false; }
|
||||
|
||||
if (a[1] > b[1]) { return true; }
|
||||
if (a[1] < b[1]) { return false; }
|
||||
|
||||
if (a[2] > b[2]) { return true; }
|
||||
if (a[2] < b[2]) { return false; }
|
||||
|
||||
if (a.length > 3) {
|
||||
// rc/beta suffix
|
||||
if (b.length <= 3) {
|
||||
return false;
|
||||
} // no suffix on b -> a<b
|
||||
return a[3] >= b[3];
|
||||
}
|
||||
if (b.length > 3) {
|
||||
// b has a suffix but a not -> a>b
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Sort versions from lowest to highest
|
||||
var sortVersions = function (versions) {
|
||||
if (!_.isArray(versions)) versions = [versions];
|
||||
|
||||
return _.uniq(versions).sort(function (a, b) {
|
||||
return compare(a, b) ? -1 : 1;
|
||||
});
|
||||
};
|
||||
|
||||
// Get the max version in this cluster
|
||||
var max = function (versions) {
|
||||
return sortVersions(versions).pop();
|
||||
};
|
||||
|
||||
// Return the lowest version in the cluster
|
||||
var min = function (versions) {
|
||||
return sortVersions(versions).shift();
|
||||
};
|
||||
|
||||
// Check if the lowest version in the cluster is >= to `version`
|
||||
var gte = function (version, versions) {
|
||||
var _versions = sortVersions(versions);
|
||||
return compare(version, min(_versions));
|
||||
};
|
||||
|
||||
// Check if the highest version in the cluster is <= to `version`
|
||||
var lte = function (version, versions) {
|
||||
var _versions = sortVersions(versions);
|
||||
return compare(max(_versions), version);
|
||||
};
|
||||
|
||||
// check if lowest version in cluster = `version`
|
||||
var eq = function (version, versions) {
|
||||
var _versions = sortVersions(versions);
|
||||
return version === min(_versions) ? true : false;
|
||||
};
|
||||
|
||||
// version > lowest version in cluster?
|
||||
var gt = function (version, versions) {
|
||||
var _versions = sortVersions(versions);
|
||||
return version === min(_versions) ? false : gte(version, _versions);
|
||||
};
|
||||
|
||||
// version < highest version in cluster?
|
||||
var lt = function (version, versions) {
|
||||
var _versions = sortVersions(versions);
|
||||
return version === max(_versions) ? false : lte(version, _versions);
|
||||
};
|
||||
|
||||
/*
|
||||
Takes a version string with one of the following optional comparison prefixes: >,>=,<.<=
|
||||
and evaluates if the cluster meets the requirement. If the prefix is omitted exact match
|
||||
is assumed
|
||||
*/
|
||||
var is = function (equation, versions) {
|
||||
var _versions = sortVersions(versions);
|
||||
var _v = equation;
|
||||
var _cf;
|
||||
|
||||
if (_v.charAt(0) === '>') {
|
||||
_cf = _v.charAt(1) === '=' ? gte(_v.slice(2), _versions) : gt(_v.slice(1), _versions);
|
||||
} else if (_v.charAt(0) === '<') {
|
||||
_cf = _v.charAt(1) === '=' ? lte(_v.slice(2), _versions) : lt(_v.slice(1), _versions);
|
||||
} else {
|
||||
_cf = eq(_v, _versions);
|
||||
}
|
||||
|
||||
return _cf;
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
min: min,
|
||||
max: max,
|
||||
is: is,
|
||||
eq: eq,
|
||||
gt: gt,
|
||||
gte: gte,
|
||||
lt: lt,
|
||||
lte: lte
|
||||
};
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
var root = require('requirefrom')('');
|
||||
var upgradeConfig = root('src/server/lib/upgradeConfig');
|
||||
var expect = require('expect.js');
|
||||
var sinon = require('sinon');
|
||||
var sinonAsPromised = require('sinon-as-promised')(require('bluebird'));
|
||||
var util = require('util');
|
||||
var package = root('package.json');
|
||||
var config = root('src/server/config');
|
||||
|
||||
var upgradeFrom4_0_0_to_4_0_1 = root('test/unit/fixtures/config_upgrade_from_4.0.0_to_4.0.1.json');
|
||||
var upgradeFrom4_0_0_to_4_0_1_snapshot = root('test/unit/fixtures/config_upgrade_from_4.0.0_to_4.0.1-snapshot.json');
|
||||
var upgradeFrom4_0_0 = root('test/unit/fixtures/config_upgrade_from_4.0.0.json');
|
||||
upgradeFrom4_0_0_to_4_0_1.hits.hits[0]._index = config.kibana.kibana_index;
|
||||
upgradeFrom4_0_0_to_4_0_1.hits.hits[1]._index = config.kibana.kibana_index;
|
||||
upgradeFrom4_0_0_to_4_0_1_snapshot.hits.hits[0]._index = config.kibana.kibana_index;
|
||||
upgradeFrom4_0_0_to_4_0_1_snapshot.hits.hits[1]._index = config.kibana.kibana_index;
|
||||
upgradeFrom4_0_0.hits.hits[0]._index = config.kibana.kibana_index;
|
||||
|
||||
describe('lib/upgradeConfig', function () {
|
||||
|
||||
var client, oldPackageVersion, oldBuildNum;
|
||||
beforeEach(function () {
|
||||
oldPackageVersion = config.package.version;
|
||||
oldBuildNum = config.buildNum;
|
||||
client = { create: sinon.stub() };
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
config.package.version = oldPackageVersion;
|
||||
config.buildNum = oldBuildNum;
|
||||
});
|
||||
|
||||
it('should not upgrade if the current version of the config exits', function () {
|
||||
config.package.version = '4.0.1';
|
||||
var fn = upgradeConfig(client);
|
||||
client.create.rejects(new Error('DocumentAlreadyExistsException'));
|
||||
return fn(upgradeFrom4_0_0_to_4_0_1).finally(function () {
|
||||
sinon.assert.notCalled(client.create);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not upgrade if there are no hits', function () {
|
||||
config.package.version = '4.0.1';
|
||||
var fn = upgradeConfig(client);
|
||||
return fn({ hits: { hits: [] } }).finally(function () {
|
||||
sinon.assert.notCalled(client.create);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not upgrade even if a snapshot exists', function () {
|
||||
config.package.version = '4.0.1-snapshot';
|
||||
client.create.rejects(new Error('DocumentAlreadyExistsException'));
|
||||
var fn = upgradeConfig(client);
|
||||
return fn(upgradeFrom4_0_0_to_4_0_1_snapshot).finally(function () {
|
||||
sinon.assert.notCalled(client.create);
|
||||
});
|
||||
});
|
||||
|
||||
it('should upgrade from 4.0.0 to 4.0.1', function () {
|
||||
config.package.version = '4.0.1';
|
||||
config.buildNum = 5921;
|
||||
var fn = upgradeConfig(client);
|
||||
client.create.resolves({ _index: config.kibana.kibana_index, _type: 'config', _id: '4.0.1', _version: 1, created: true });
|
||||
return fn(upgradeFrom4_0_0).finally(function () {
|
||||
sinon.assert.calledOnce(client.create);
|
||||
var body = client.create.args[0][0];
|
||||
expect(body).to.eql({
|
||||
index: config.kibana.kibana_index,
|
||||
type: 'config',
|
||||
id: '4.0.1',
|
||||
body: {
|
||||
'buildNum': 5921,
|
||||
'defaultIndex': 'logstash-*'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -1,194 +0,0 @@
|
|||
var _ = require('lodash');
|
||||
var root = require('requirefrom')('');
|
||||
var validateRequest = root('src/hapi/plugins/elasticsearch/lib/validate');
|
||||
var expect = require('expect.js');
|
||||
var server = { config: root('src/hapi/lib/config') };
|
||||
var config = server.config();
|
||||
|
||||
describe('lib/isValid', function () {
|
||||
|
||||
function del(path, body, valid) {
|
||||
run('delEte', path, body, valid);
|
||||
run('delete', path, body, valid);
|
||||
}
|
||||
|
||||
function send(path, body, valid) {
|
||||
run('POST', path, body, valid);
|
||||
run('post', path, body, valid);
|
||||
run('PUT', path, body, valid);
|
||||
run('put', path, body, valid);
|
||||
}
|
||||
|
||||
function run(method, path, body, valid) {
|
||||
if (typeof body === 'boolean') {
|
||||
valid = body;
|
||||
body = null;
|
||||
}
|
||||
|
||||
if (_.isArray(body)) body = body.map(JSON.stringify).join('\n') + '\n';
|
||||
if (_.isObject(body)) body = JSON.stringify(body);
|
||||
|
||||
var pass = false;
|
||||
try {
|
||||
validateRequest(server, {
|
||||
method: method.toLowerCase(),
|
||||
path: path,
|
||||
payload: body
|
||||
});
|
||||
pass = true;
|
||||
} catch (e) {}
|
||||
|
||||
if (pass !== Boolean(valid)) {
|
||||
var msg = 'Expected ' + method + ' ' +
|
||||
path + ' ' + (body ? 'with body ' : '') +
|
||||
'to ' + (!valid ? 'not ' : '') + 'validate';
|
||||
|
||||
if (body) {
|
||||
msg += ' – ' + body;
|
||||
}
|
||||
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
describe('index management', function () {
|
||||
it('allows creating kibana index', function () {
|
||||
send('/' + config.get('kibana.index'), true);
|
||||
});
|
||||
|
||||
it('allows deleting the kibana index', function () {
|
||||
del('/' + config.get('kibana.index'), true);
|
||||
});
|
||||
|
||||
it('blocks creating a non-kibana index', function () {
|
||||
send('/app-index', false);
|
||||
});
|
||||
|
||||
it('blocks deleting a non-kibana indices', function () {
|
||||
del('/app-data', false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('doc management', function () {
|
||||
it('allows indexing to the kibana index', function () {
|
||||
send('/' + config.get('kibana.index'), true);
|
||||
send('/' + config.get('kibana.index') + '/index-patterns', true);
|
||||
send('/' + config.get('kibana.index') + '/index-patterns/pattern-id', true);
|
||||
});
|
||||
|
||||
it('allows deleting kibana documents', function () {
|
||||
del('/' + config.get('kibana.index') + '/index-patterns', true);
|
||||
del('/' + config.get('kibana.index') + '/index-patterns/pattern-id', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('allows any destructive non-bulk requests against kibana index', function () {
|
||||
it('refresh', function () {
|
||||
send('/' + config.get('kibana.index') + '/_refresh', true);
|
||||
});
|
||||
|
||||
it('delete', function () {
|
||||
del('/' + config.get('kibana.index') + '/pasta/lasagna', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('assorted methods that are non-destructive', function () {
|
||||
it('validate', function () {
|
||||
run('GET', '/_search?search_type=count', true);
|
||||
run('GET', '/index/type/id', true);
|
||||
run('GET', '/index/type/_mapping/field/field1', true);
|
||||
run('GET', '/_aliases', true);
|
||||
run('GET', '/_nodes/', true);
|
||||
run('HEAD', '/', true);
|
||||
run('HEAD', '/' + config.get('kibana.index'), true);
|
||||
run('HEAD', '/other-index', true);
|
||||
run('GET', '/_cluster/health', true);
|
||||
run('POST', '/' + config.get('kibana.index') + '/__notRealIndex__/_validate/query?q=foo:bar', true);
|
||||
run('POST', '/_validate', true);
|
||||
run('POST', '/_search', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bulk indexing', function () {
|
||||
it('valid', function () {
|
||||
send('/_bulk', [
|
||||
{ create: { _index: config.get('kibana.index'), _type: 'index-pattern' } },
|
||||
{ fields: [] },
|
||||
{ create: { _index: config.get('kibana.index'), _type: 'vis' } },
|
||||
{ aggs: [] }
|
||||
], true);
|
||||
|
||||
send('/' + config.get('kibana.index') + '/_bulk', [
|
||||
// implicit index
|
||||
{ create: { _type: 'index-pattern' } },
|
||||
{ fields: [] },
|
||||
|
||||
// explicit index
|
||||
{ create: { _index: config.get('kibana.index'), _type: 'vis' } },
|
||||
{ aggs: [] }
|
||||
|
||||
], true);
|
||||
});
|
||||
|
||||
it('rejects bulks including even one other index', function () {
|
||||
send('/' + config.get('kibana.index') + '/_bulk', [
|
||||
// implicit index
|
||||
{ create: { _type: 'index-pattern' } },
|
||||
{ fields: [] },
|
||||
// explicit index
|
||||
{ create: { _index: 'app-data', _type: 'vis' } },
|
||||
{ aggs: [] }
|
||||
], false);
|
||||
});
|
||||
|
||||
it('rejects malformed bulk bodies', function () {
|
||||
send('/_bulk', '{}\n{ "_index": "john" }\n', false);
|
||||
send('/_bulk', '{}\n{}\n', false);
|
||||
send('/_bulk', '{ "field": "value" }', false);
|
||||
send('/_bulk', '{ "field": "v', false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('msearch', function () {
|
||||
it('requires a bulk-formatted body', function () {
|
||||
send('/_msearch', false);
|
||||
send('/_msearch', '{}', false);
|
||||
send('/_msearch', '{}\n{}\n', true);
|
||||
send('/_msearch', '{}\n{}\n{}\n', false);
|
||||
});
|
||||
|
||||
it('allows searching any index', function () {
|
||||
send('/app-index/_msearch', [
|
||||
{},
|
||||
{ query: { match_all: {} } }
|
||||
], true);
|
||||
|
||||
send('/app-index/data-type/_msearch', [
|
||||
{},
|
||||
{ query: { match_all: {} } }
|
||||
], true);
|
||||
|
||||
send('/_msearch', [
|
||||
{ _index: 'app-index', _type: 'data-type' },
|
||||
{ query: { match_all: {} } },
|
||||
{ _index: 'IT-index', _type: 'logs' },
|
||||
{ query: { match_all: {} } },
|
||||
{ _index: 'L33t', _type: '?' },
|
||||
{ query: { match_all: {} } },
|
||||
], true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mget', function () {
|
||||
it('requires a valid json body', function () {
|
||||
send('/_mget', false);
|
||||
send('/_mget', '{}', true);
|
||||
send('/_mget', '{}\n{}\n', false);
|
||||
});
|
||||
|
||||
it('allows reading from any index', function () {
|
||||
send('/app-index/_mget', { docs: { match_all: {} } }, true);
|
||||
send('/app-index/data-type/_mget', { docs: [ {} ] }, true);
|
||||
});
|
||||
});
|
||||
});
|
70
test/unit/server/plugins/elasticsearch/check_es_version.js
Normal file
70
test/unit/server/plugins/elasticsearch/check_es_version.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
var root = require('requirefrom')('');
|
||||
var _ = require('lodash');
|
||||
var checkEsVersion = root('src/hapi/plugins/elasticsearch/lib/check_es_version');
|
||||
var Promise = require('bluebird');
|
||||
var sinon = require('sinon');
|
||||
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('lib/check_es_version', function () {
|
||||
var server;
|
||||
|
||||
beforeEach(function () {
|
||||
var get = sinon.stub().withArgs('elasticserach.minimumVerison').returns('1.4.3');
|
||||
var config = function () { return { get: get }; };
|
||||
server = { config: config, plugins: { elasticsearch: { client: { nodes: {} } } } };
|
||||
});
|
||||
|
||||
function setNodes(/* ...versions */) {
|
||||
var versions = _.shuffle(arguments);
|
||||
var nodes = {};
|
||||
var i = 0;
|
||||
|
||||
while (versions.length) {
|
||||
var name = 'node-' + (++i);
|
||||
var version = versions.shift();
|
||||
|
||||
var node = {
|
||||
version: version,
|
||||
http_address: 'http_address',
|
||||
ip: 'ip'
|
||||
};
|
||||
|
||||
if (!_.isString(version)) _.assign(node, version);
|
||||
nodes[name] = node;
|
||||
}
|
||||
|
||||
var client = server.plugins.elasticsearch.client;
|
||||
client.nodes.info = sinon.stub().returns(Promise.resolve({ nodes: nodes }));
|
||||
|
||||
}
|
||||
|
||||
it('passes with single a node that matches', function () {
|
||||
setNodes('1.4.3');
|
||||
return checkEsVersion(server)();
|
||||
});
|
||||
|
||||
it('passes with multiple nodes that satisfy', function () {
|
||||
setNodes('1.4.3', '1.4.4', '1.4.3-Beta1');
|
||||
return checkEsVersion(server)();
|
||||
});
|
||||
|
||||
it('fails with a single node that is out of date', function () {
|
||||
setNodes('1.4.4', '1.4.2', '1.4.5');
|
||||
return checkEsVersion(server)()
|
||||
.then(function () {
|
||||
throw new Error('expected validation to fail');
|
||||
}, _.noop);
|
||||
});
|
||||
|
||||
it('passes if that single node is a client node', function () {
|
||||
setNodes(
|
||||
'1.4.4',
|
||||
{ version: '1.4.2', attributes: { client: 'true' } },
|
||||
'1.4.5'
|
||||
);
|
||||
|
||||
return checkEsVersion(server)();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
140
test/unit/server/plugins/elasticsearch/create_kibana_index.js
Normal file
140
test/unit/server/plugins/elasticsearch/create_kibana_index.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
var root = require('requirefrom')('');
|
||||
var _ = require('lodash');
|
||||
_.mixin(require('lodash-deep'));
|
||||
var sinon = require('sinon');
|
||||
var expect = require('expect.js');
|
||||
var createKibanaIndex = root('src/hapi/plugins/elasticsearch/lib/create_kibana_index');
|
||||
var SetupError = root('src/hapi/plugins/elasticsearch/lib/setup_error');
|
||||
var Promise = require('bluebird');
|
||||
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('lib/create_kibana_index', function () {
|
||||
|
||||
var server, client, config;
|
||||
beforeEach(function () {
|
||||
server = {};
|
||||
client = {};
|
||||
var config = { kibana: { index: '.my-kibana' } };
|
||||
var get = sinon.stub();
|
||||
get.returns(config);
|
||||
get.withArgs('kibana.index').returns(config.kibana.index);
|
||||
config = function () { return { get: get }; };
|
||||
_.deepSet(client, 'indices.create', sinon.stub());
|
||||
_.deepSet(client, 'cluster.health', sinon.stub());
|
||||
_.deepSet(server, 'plugins.elasticsearch.client', client);
|
||||
_.deepSet(server, 'config', config);
|
||||
});
|
||||
|
||||
describe('successful requests', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
client.indices.create.returns(Promise.resolve());
|
||||
client.cluster.health.returns(Promise.resolve());
|
||||
});
|
||||
|
||||
it('should check cluster.health upon successful index creation', function () {
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.then(function () {
|
||||
sinon.assert.calledOnce(client.cluster.health);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created with mappings for config.buildNum', function () {
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.then(function () {
|
||||
var params = client.indices.create.args[0][0];
|
||||
expect(params)
|
||||
.to.have.property('body');
|
||||
expect(params.body)
|
||||
.to.have.property('mappings');
|
||||
expect(params.body.mappings)
|
||||
.to.have.property('config');
|
||||
expect(params.body.mappings.config)
|
||||
.to.have.property('properties');
|
||||
expect(params.body.mappings.config.properties)
|
||||
.to.have.property('buildNum');
|
||||
expect(params.body.mappings.config.properties.buildNum)
|
||||
.to.have.property('type', 'string');
|
||||
expect(params.body.mappings.config.properties.buildNum)
|
||||
.to.have.property('index', 'not_analyzed');
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created with 1 shard and 1 replica', function () {
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.then(function () {
|
||||
var params = client.indices.create.args[0][0];
|
||||
expect(params)
|
||||
.to.have.property('body');
|
||||
expect(params.body)
|
||||
.to.have.property('settings');
|
||||
expect(params.body.settings)
|
||||
.to.have.property('number_of_shards', 1);
|
||||
expect(params.body.settings)
|
||||
.to.have.property('number_of_replicas', 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created with 1 shard and 1 replica', function () {
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.then(function () {
|
||||
var params = client.indices.create.args[0][0];
|
||||
expect(params)
|
||||
.to.have.property('body');
|
||||
expect(params.body)
|
||||
.to.have.property('settings');
|
||||
expect(params.body.settings)
|
||||
.to.have.property('number_of_shards', 1);
|
||||
expect(params.body.settings)
|
||||
.to.have.property('number_of_replicas', 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created with index name set in the config', function () {
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.then(function () {
|
||||
var params = client.indices.create.args[0][0];
|
||||
expect(params)
|
||||
.to.have.property('index', '.my-kibana');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe('failure requests', function () {
|
||||
it('should reject with a SetupError', function () {
|
||||
var error = new Error('Oops!');
|
||||
client.indices.create.returns(Promise.reject(error));
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.catch(function (err) {
|
||||
expect(err).to.be.a(SetupError);
|
||||
});
|
||||
});
|
||||
|
||||
it('should reject with an error if index creation fails', function () {
|
||||
var error = new Error('Oops!');
|
||||
client.indices.create.returns(Promise.reject(error));
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.catch(function (err) {
|
||||
expect(err.message).to.be('Unable to create Kibana index ".my-kibana"');
|
||||
expect(err).to.have.property('origError', error);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should reject with an error if health check fails', function () {
|
||||
var error = new Error('Oops!');
|
||||
client.indices.create.returns(Promise.resolve());
|
||||
client.cluster.health.returns(Promise.reject(error));
|
||||
var fn = createKibanaIndex(server);
|
||||
return fn.catch(function (err) {
|
||||
expect(err.message).to.be('Waiting for Kibana index ".my-kibana" to come online failed.');
|
||||
expect(err).to.have.property('origError', error);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
147
test/unit/server/plugins/elasticsearch/health_check.js
Normal file
147
test/unit/server/plugins/elasticsearch/health_check.js
Normal file
|
@ -0,0 +1,147 @@
|
|||
var root = require('requirefrom')('');
|
||||
var _ = require('lodash');
|
||||
var healthCheck = root('src/hapi/plugins/elasticsearch/lib/health_check');
|
||||
var Promise = require('bluebird');
|
||||
var sinon = require('sinon');
|
||||
var root = require('requirefrom')('');
|
||||
var _ = require('lodash');
|
||||
var healthCheck = root('src/hapi/plugins/elasticsearch/lib/health_check');
|
||||
var Promise = require('bluebird');
|
||||
var sinon = require('sinon');
|
||||
var expect = require('expect.js');
|
||||
var NoConnections = require('elasticsearch').errors.NoConnections;
|
||||
|
||||
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('lib/health_check', function () {
|
||||
|
||||
var health, plugin, server, get, client;
|
||||
beforeEach(function () {
|
||||
// setup the plugin stub
|
||||
plugin = {
|
||||
name: 'elasticsearch',
|
||||
status: {
|
||||
red: sinon.stub(),
|
||||
green: sinon.stub(),
|
||||
yellow: sinon.stub()
|
||||
}
|
||||
};
|
||||
// setup the config().get() stub
|
||||
get = sinon.stub();
|
||||
// set up the elasticsearch client stub
|
||||
client = {
|
||||
cluster: { health: sinon.stub() },
|
||||
indices: { create: sinon.stub() },
|
||||
nodes: { info: sinon.stub() },
|
||||
ping: sinon.stub(),
|
||||
create: sinon.stub(),
|
||||
search: sinon.stub().returns(Promise.resolve({ hits: { hits: [] } })),
|
||||
};
|
||||
client.nodes.info.returns(Promise.resolve({
|
||||
nodes: {
|
||||
'node-01': {
|
||||
version: '1.5.0',
|
||||
http_address: 'inet[/127.0.0.1:9200]',
|
||||
ip: '127.0.0.1'
|
||||
}
|
||||
}
|
||||
}));
|
||||
// Setup the server mock
|
||||
server = {
|
||||
log: sinon.stub(),
|
||||
config: function () { return { get: get }; },
|
||||
plugins: { elasticsearch: { client: client } }
|
||||
};
|
||||
|
||||
health = healthCheck(plugin, server);
|
||||
});
|
||||
|
||||
it('should set the cluster green if everything is ready', function () {
|
||||
get.withArgs('elasticsearch.minimumVerison').returns('1.4.4');
|
||||
get.withArgs('kibana.index').returns('.my-kibana');
|
||||
client.ping.returns(Promise.resolve());
|
||||
client.cluster.health.returns(Promise.resolve({ timed_out: false, status: 'green' }));
|
||||
return health.run()
|
||||
.then(function () {
|
||||
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.calledOnce(client.cluster.health);
|
||||
sinon.assert.calledOnce(plugin.status.green);
|
||||
expect(plugin.status.green.args[0][0]).to.be('Kibana index ready');
|
||||
});
|
||||
});
|
||||
|
||||
it('should set the cluster red if the ping fails, then to green', function () {
|
||||
this.timeout(3000);
|
||||
get.withArgs('elasticsearch.url').returns('http://localhost:9200');
|
||||
get.withArgs('elasticsearch.minimumVerison').returns('1.4.4');
|
||||
get.withArgs('kibana.index').returns('.my-kibana');
|
||||
client.ping.onCall(0).returns(Promise.reject(new NoConnections()));
|
||||
client.ping.onCall(1).returns(Promise.resolve());
|
||||
client.cluster.health.returns(Promise.resolve({ timed_out: false, status: 'green' }));
|
||||
return health.run()
|
||||
.then(function () {
|
||||
sinon.assert.calledOnce(plugin.status.yellow);
|
||||
expect(plugin.status.yellow.args[0][0]).to.be('Waiting for Elasticsearch');
|
||||
sinon.assert.calledOnce(plugin.status.red);
|
||||
/* jscs:disable maximumLineLength */
|
||||
expect(plugin.status.red.args[0][0]).to.be('Unable to connect to Elasticsearch at http://localhost:9200. Retrying in 2.5 seconds.');
|
||||
/* jscs:enable maximumLineLength */
|
||||
sinon.assert.calledTwice(client.ping);
|
||||
sinon.assert.calledOnce(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');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should set the cluster red if the health check status is red, then to green', function () {
|
||||
this.timeout(3000);
|
||||
get.withArgs('elasticsearch.url').returns('http://localhost:9200');
|
||||
get.withArgs('elasticsearch.minimumVerison').returns('1.4.4');
|
||||
get.withArgs('kibana.index').returns('.my-kibana');
|
||||
client.ping.returns(Promise.resolve());
|
||||
client.cluster.health.onCall(0).returns(Promise.resolve({ timed_out: false, status: 'red' }));
|
||||
client.cluster.health.onCall(1).returns(Promise.resolve({ timed_out: false, status: 'green' }));
|
||||
return health.run()
|
||||
.then(function () {
|
||||
sinon.assert.calledOnce(plugin.status.yellow);
|
||||
expect(plugin.status.yellow.args[0][0]).to.be('Waiting for Elasticsearch');
|
||||
sinon.assert.calledOnce(plugin.status.red);
|
||||
/* jscs:disable maximumLineLength */
|
||||
expect(plugin.status.red.args[0][0]).to.be('Elasticsearch is still initializing the kibana index... Trying again in 2.5 second.');
|
||||
/* jscs:enable maximumLineLength */
|
||||
sinon.assert.calledOnce(client.ping);
|
||||
sinon.assert.calledOnce(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');
|
||||
});
|
||||
});
|
||||
|
||||
it('should set the cluster yellow if the health check timed_out and create index', function () {
|
||||
this.timeout(3000);
|
||||
get.withArgs('elasticsearch.url').returns('http://localhost:9200');
|
||||
get.withArgs('elasticsearch.minimumVerison').returns('1.4.4');
|
||||
get.withArgs('kibana.index').returns('.my-kibana');
|
||||
client.ping.returns(Promise.resolve());
|
||||
client.cluster.health.onCall(0).returns(Promise.resolve({ timed_out: true, status: 'red' }));
|
||||
client.cluster.health.onCall(1).returns(Promise.resolve({ timed_out: false, status: 'green' }));
|
||||
client.indices.create.returns(Promise.resolve());
|
||||
return health.run()
|
||||
.then(function () {
|
||||
sinon.assert.calledTwice(plugin.status.yellow);
|
||||
expect(plugin.status.yellow.args[0][0]).to.be('Waiting for 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.cluster.health);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
69
test/unit/server/plugins/elasticsearch/is_upgradeable.js
Normal file
69
test/unit/server/plugins/elasticsearch/is_upgradeable.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
var root = require('requirefrom')('');
|
||||
var isUpgradeable = root('src/hapi/plugins/elasticsearch/lib/is_upgradeable');
|
||||
var expect = require('expect.js');
|
||||
var util = require('util');
|
||||
var package = root('package.json');
|
||||
var sinon = require('sinon');
|
||||
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('lib/isUpgradeable', function () {
|
||||
|
||||
var config = {};
|
||||
var server = {
|
||||
config: function () {
|
||||
return config;
|
||||
}
|
||||
};
|
||||
|
||||
function upgradeDoc(_id, version, bool) {
|
||||
it(util.format('should return %s for %s <= %s', bool, _id, version), function () {
|
||||
var doc = { _id: _id };
|
||||
config.get = sinon.stub().withArgs('kibana.package.version').returns(version);
|
||||
expect(isUpgradeable(server, doc)).to.be(bool);
|
||||
});
|
||||
}
|
||||
|
||||
upgradeDoc('1.0.0-beta1', package.version, false);
|
||||
upgradeDoc(package.version, package.version, false);
|
||||
upgradeDoc('4.0.0-RC1', '4.0.0-RC2', true);
|
||||
upgradeDoc('4.0.0-rc2', '4.0.0-rc1', false);
|
||||
upgradeDoc('4.0.0-rc2', '4.0.0', true);
|
||||
upgradeDoc('4.0.0-rc2', '4.0.2', true);
|
||||
upgradeDoc('4.0.1', '4.1.0-rc', true);
|
||||
upgradeDoc('4.0.0-rc1', '4.0.0', true);
|
||||
upgradeDoc('4.0.0-rc1-snapshot', '4.0.0', false);
|
||||
upgradeDoc('4.1.0-rc1-snapshot', '4.1.0-rc1', false);
|
||||
|
||||
it('should handle missing _id field', function () {
|
||||
config.get = sinon.stub().withArgs('kibana.package.version').returns(package.version);
|
||||
var doc = {
|
||||
'_index': '.kibana',
|
||||
'_type': 'config',
|
||||
'_score': 1,
|
||||
'_source': {
|
||||
'buildNum': 1.7976931348623157e+308,
|
||||
'defaultIndex': '[logstash-]YYYY.MM.DD'
|
||||
}
|
||||
};
|
||||
expect(isUpgradeable(server, doc)).to.be(false);
|
||||
});
|
||||
|
||||
it('should handle _id of @@version', function () {
|
||||
config.get = sinon.stub().withArgs('kibana.package.version').returns(package.version);
|
||||
var doc = {
|
||||
'_index': '.kibana',
|
||||
'_type': 'config',
|
||||
'_id': '@@version',
|
||||
'_score': 1,
|
||||
'_source': {
|
||||
'buildNum': 1.7976931348623157e+308,
|
||||
'defaultIndex': '[logstash-]YYYY.MM.DD'
|
||||
}
|
||||
};
|
||||
expect(isUpgradeable(server, doc)).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
|
@ -7,95 +7,97 @@ var util = require('util');
|
|||
var format = util.format;
|
||||
|
||||
|
||||
describe('elasticsearch plugin', function () {
|
||||
var server, config;
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('routes', function () {
|
||||
var server, config;
|
||||
|
||||
beforeEach(function () {
|
||||
return findPort(7000, 8000).then(function (port) {
|
||||
config = { 'kibana.server.port': port, 'logging.quiet': true };
|
||||
return kibana.start(config).then(function (_server) {
|
||||
server = _server;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
server.stop(done);
|
||||
});
|
||||
|
||||
function testRoute(options) {
|
||||
var statusCode = options.statusCode || 200;
|
||||
describe(format('%s %s', options.method, options.url), function () {
|
||||
it('should should return ' + statusCode, function (done) {
|
||||
server.inject(options, function (res) {
|
||||
expect(res.statusCode).to.be(statusCode);
|
||||
done();
|
||||
beforeEach(function () {
|
||||
return findPort(7000, 8000).then(function (port) {
|
||||
config = { 'kibana.server.port': port, 'logging.quiet': true };
|
||||
return kibana.start(config).then(function (_server) {
|
||||
server = _server;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
afterEach(function (done) {
|
||||
server.stop(done);
|
||||
});
|
||||
|
||||
function testRoute(options) {
|
||||
var statusCode = options.statusCode || 200;
|
||||
describe(format('%s %s', options.method, options.url), function () {
|
||||
it('should should return ' + statusCode, function (done) {
|
||||
server.inject(options, function (res) {
|
||||
expect(res.statusCode).to.be(statusCode);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/_nodes'
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/_nodes'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/.kibana'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana',
|
||||
payload: '{settings: {number_of_shards: 1, number_of_replicas: 1}}',
|
||||
statusCode: 201
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana/_bulk',
|
||||
payload: '{}',
|
||||
statusCode: 400
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/.kibana/_mapping/*/field/_source'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana/index-pattern/_search?fields=',
|
||||
payload: '{query: {match_all: {}}, size: 2147483647}'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana/__kibanaQueryValidator/_validate/query?explain=true&ignore_unavailable=true',
|
||||
payload: '{query: {query_string: {analyze_wildcard: true, query: "*"}}}'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/_mget?timeout=0&ignore_unavailable=true&preference=1429574531063',
|
||||
payload: '{docs: [{_index: ".kibana", _type: "index-pattern", _id: "[logstash-]YYYY.MM.DD"}]}'
|
||||
});
|
||||
|
||||
/* jscs:disable maximumLineLength */
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/_msearch?timeout=0&ignore_unavailable=true&preference=1429577952339',
|
||||
payload: '{"index":"logstash-2015.04.21","ignore_unavailable":true}\n{"size":500,"sort":{"@timestamp":"desc"},"query":{"filtered":{"query":{"query_string":{"analyze_wildcard":true,"query":"*"}},"filter":{"bool":{"must":[{"range":{"@timestamp":{"gte":1429577068175,"lte":1429577968175}}}],"must_not":[]}}}},"highlight":{"pre_tags":["@kibana-highlighted-field@"],"post_tags":["@/kibana-highlighted-field@"],"fields":{"*":{}}},"aggs":{"2":{"date_histogram":{"field":"@timestamp","interval":"30s","pre_zone":"-07:00","pre_zone_adjust_large_interval":true,"min_doc_count":0,"extended_bounds":{"min":1429577068175,"max":1429577968175}}}},"fields":["*","_source"],"script_fields":{},"fielddata_fields":["timestamp_offset","@timestamp","utc_time"]}\n'
|
||||
});
|
||||
/* jscs:enable maximumLineLength */
|
||||
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/.kibana'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana',
|
||||
payload: '{settings: {number_of_shards: 1, number_of_replicas: 1}}',
|
||||
statusCode: 201
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana/_bulk',
|
||||
payload: '{}',
|
||||
statusCode: 400
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'GET',
|
||||
url: '/elasticsearch/.kibana/_mapping/*/field/_source'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana/index-pattern/_search?fields=',
|
||||
payload: '{query: {match_all: {}}, size: 2147483647}'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/.kibana/__kibanaQueryValidator/_validate/query?explain=true&ignore_unavailable=true',
|
||||
payload: '{query: {query_string: {analyze_wildcard: true, query: "*"}}}'
|
||||
});
|
||||
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/_mget?timeout=0&ignore_unavailable=true&preference=1429574531063',
|
||||
payload: '{docs: [{_index: ".kibana", _type: "index-pattern", _id: "[logstash-]YYYY.MM.DD"}]}'
|
||||
});
|
||||
|
||||
/* jscs:disable maximumLineLength */
|
||||
testRoute({
|
||||
method: 'POST',
|
||||
url: '/elasticsearch/_msearch?timeout=0&ignore_unavailable=true&preference=1429577952339',
|
||||
payload: '{"index":"logstash-2015.04.21","ignore_unavailable":true}\n{"size":500,"sort":{"@timestamp":"desc"},"query":{"filtered":{"query":{"query_string":{"analyze_wildcard":true,"query":"*"}},"filter":{"bool":{"must":[{"range":{"@timestamp":{"gte":1429577068175,"lte":1429577968175}}}],"must_not":[]}}}},"highlight":{"pre_tags":["@kibana-highlighted-field@"],"post_tags":["@/kibana-highlighted-field@"],"fields":{"*":{}}},"aggs":{"2":{"date_histogram":{"field":"@timestamp","interval":"30s","pre_zone":"-07:00","pre_zone_adjust_large_interval":true,"min_doc_count":0,"extended_bounds":{"min":1429577068175,"max":1429577968175}}}},"fields":["*","_source"],"script_fields":{},"fielddata_fields":["timestamp_offset","@timestamp","utc_time"]}\n'
|
||||
});
|
||||
/* jscs:enable maximumLineLength */
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
53
test/unit/server/plugins/elasticsearch/setup_error.js
Normal file
53
test/unit/server/plugins/elasticsearch/setup_error.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
var root = require('requirefrom')('');
|
||||
var _ = require('lodash');
|
||||
var SetupError = root('src/hapi/plugins/elasticsearch/lib/setup_error');
|
||||
var expect = require('expect.js');
|
||||
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('lib/setup_error', function () {
|
||||
|
||||
var server = {
|
||||
config: function () {
|
||||
return {
|
||||
get: function () {
|
||||
return { kibana: { index: '.my-kibana' } };
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var err = new SetupError(server, 'Oops! <%= kibana.index %>');
|
||||
|
||||
it('should allow config values in the message template', function () {
|
||||
expect(err).to.have.property('message', 'Oops! .my-kibana');
|
||||
});
|
||||
|
||||
it('should set the name of the error', function () {
|
||||
expect(err).to.have.property('name', 'SetupError');
|
||||
});
|
||||
|
||||
it('should set the stack trace', function () {
|
||||
expect(err).to.have.property('stack');
|
||||
expect(err.stack).to.match(/^SetupError/);
|
||||
});
|
||||
|
||||
it('should return the passed error if it is a SetupError', function () {
|
||||
var error = new SetupError(server, 'Oh Boy!', err);
|
||||
expect(error).to.have.property('message', 'Oops! .my-kibana');
|
||||
});
|
||||
|
||||
it('should store the original error', function () {
|
||||
var origError = new Error('Boom!');
|
||||
var error = new SetupError(server, 'Oh Boy!', origError);
|
||||
expect(error).to.have.property('origError', origError);
|
||||
});
|
||||
|
||||
it('should copy the stack from the origError', function () {
|
||||
var origError = new Error('Boom!');
|
||||
var error = new SetupError(server, 'Oh Boy!', origError);
|
||||
expect(error).to.have.property('stack', origError.stack);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
96
test/unit/server/plugins/elasticsearch/upgrade_config.js
Normal file
96
test/unit/server/plugins/elasticsearch/upgrade_config.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
var root = require('requirefrom')('');
|
||||
var _ = require('lodash');
|
||||
var upgradeConfig = root('src/hapi/plugins/elasticsearch/lib/upgrade_config');
|
||||
var Promise = require('bluebird');
|
||||
var sinon = require('sinon');
|
||||
var expect = require('expect.js');
|
||||
|
||||
describe('pluigns/elasticsearch', function () {
|
||||
describe('lib/upgrade_config', function () {
|
||||
|
||||
var get, server, client, config, upgrade;
|
||||
beforeEach(function () {
|
||||
get = sinon.stub();
|
||||
get.withArgs('kibana.package.version').returns('4.0.1');
|
||||
get.withArgs('kibana.index').returns('.my-kibana');
|
||||
client = { create: sinon.stub() };
|
||||
server = {
|
||||
log: sinon.stub(),
|
||||
config: function () { return { get: get }; },
|
||||
plugins: { elasticsearch: { client: client } }
|
||||
};
|
||||
upgrade = upgradeConfig(server);
|
||||
});
|
||||
|
||||
it('should resolve with undefined if nothing is found', function () {
|
||||
return upgrade({ hits: { hits:[] } }).then(function (resp) {
|
||||
expect(resp).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve with undefined if the current version is found', function () {
|
||||
var response = { hits: { hits: [ { _id: '4.0.1' } ] } };
|
||||
return upgrade(response).then(function (resp) {
|
||||
expect(resp).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve with undefined if the nothing is upgradeable', function () {
|
||||
var response = { hits: { hits: [ { _id: '4.0.1-beta1' }, { _id: '4.0.0-snapshot1' } ] } };
|
||||
return upgrade(response).then(function (resp) {
|
||||
expect(resp).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
it('should update the build number on the new config', function () {
|
||||
get.withArgs('kibana.buildNum').returns(5801);
|
||||
client.create.returns(Promise.resolve());
|
||||
var response = { hits: { hits: [ { _id: '4.0.0', _source: { buildNum: 1 } } ] } };
|
||||
return upgrade(response).then(function (resp) {
|
||||
sinon.assert.calledOnce(client.create);
|
||||
var params = client.create.args[0][0];
|
||||
expect(params).to.have.property('body');
|
||||
expect(params.body).to.have.property('buildNum', 5801);
|
||||
expect(params).to.have.property('index', '.my-kibana');
|
||||
expect(params).to.have.property('type', 'config');
|
||||
expect(params).to.have.property('id', '4.0.1');
|
||||
});
|
||||
});
|
||||
|
||||
it('should update the build number to max integer if buildNum is template string', function () {
|
||||
get.withArgs('kibana.buildNum').returns('@@buildNum');
|
||||
client.create.returns(Promise.resolve());
|
||||
var response = { hits: { hits: [ { _id: '4.0.0', _source: { buildNum: 1 } } ] } };
|
||||
return upgrade(response).then(function (resp) {
|
||||
sinon.assert.calledOnce(client.create);
|
||||
var params = client.create.args[0][0];
|
||||
expect(params).to.have.property('body');
|
||||
expect(params.body).to.have.property('buildNum', Math.pow(2, 53) - 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should log a message for upgrades', function () {
|
||||
get.withArgs('kibana.buildNum').returns(5801);
|
||||
client.create.returns(Promise.resolve());
|
||||
var response = { hits: { hits: [ { _id: '4.0.0', _source: { buildNum: 1 } } ] } };
|
||||
return upgrade(response).then(function (resp) {
|
||||
sinon.assert.calledOnce(server.log);
|
||||
expect(server.log.args[0][0]).to.be('plugin');
|
||||
expect(server.log.args[0][1]).to.be('[ elasticsearch ] Upgrade config from 4.0.0 to 4.0.1');
|
||||
});
|
||||
});
|
||||
|
||||
it('should copy attributes from old config', function () {
|
||||
get.withArgs('kibana.buildNum').returns(5801);
|
||||
client.create.returns(Promise.resolve());
|
||||
var response = { hits: { hits: [ { _id: '4.0.0', _source: { buildNum: 1, defaultIndex: 'logstash-*' } } ] } };
|
||||
return upgrade(response).then(function (resp) {
|
||||
sinon.assert.calledOnce(client.create);
|
||||
var params = client.create.args[0][0];
|
||||
expect(params).to.have.property('body');
|
||||
expect(params.body).to.have.property('defaultIndex', 'logstash-*');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
197
test/unit/server/plugins/elasticsearch/validate.js
Normal file
197
test/unit/server/plugins/elasticsearch/validate.js
Normal file
|
@ -0,0 +1,197 @@
|
|||
var _ = require('lodash');
|
||||
var root = require('requirefrom')('');
|
||||
var validateRequest = root('src/hapi/plugins/elasticsearch/lib/validate');
|
||||
var expect = require('expect.js');
|
||||
var server = { config: root('src/hapi/lib/config') };
|
||||
var config = server.config();
|
||||
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('lib/validate', function () {
|
||||
|
||||
function del(path, body, valid) {
|
||||
run('delEte', path, body, valid);
|
||||
run('delete', path, body, valid);
|
||||
}
|
||||
|
||||
function send(path, body, valid) {
|
||||
run('POST', path, body, valid);
|
||||
run('post', path, body, valid);
|
||||
run('PUT', path, body, valid);
|
||||
run('put', path, body, valid);
|
||||
}
|
||||
|
||||
function run(method, path, body, valid) {
|
||||
if (typeof body === 'boolean') {
|
||||
valid = body;
|
||||
body = null;
|
||||
}
|
||||
|
||||
if (_.isArray(body)) body = body.map(JSON.stringify).join('\n') + '\n';
|
||||
if (_.isObject(body)) body = JSON.stringify(body);
|
||||
|
||||
var pass = false;
|
||||
try {
|
||||
validateRequest(server, {
|
||||
method: method.toLowerCase(),
|
||||
path: path,
|
||||
payload: body
|
||||
});
|
||||
pass = true;
|
||||
} catch (e) {}
|
||||
|
||||
if (pass !== Boolean(valid)) {
|
||||
var msg = 'Expected ' + method + ' ' +
|
||||
path + ' ' + (body ? 'with body ' : '') +
|
||||
'to ' + (!valid ? 'not ' : '') + 'validate';
|
||||
|
||||
if (body) {
|
||||
msg += ' – ' + body;
|
||||
}
|
||||
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
describe('index management', function () {
|
||||
it('allows creating kibana index', function () {
|
||||
send('/' + config.get('kibana.index'), true);
|
||||
});
|
||||
|
||||
it('allows deleting the kibana index', function () {
|
||||
del('/' + config.get('kibana.index'), true);
|
||||
});
|
||||
|
||||
it('blocks creating a non-kibana index', function () {
|
||||
send('/app-index', false);
|
||||
});
|
||||
|
||||
it('blocks deleting a non-kibana indices', function () {
|
||||
del('/app-data', false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('doc management', function () {
|
||||
it('allows indexing to the kibana index', function () {
|
||||
send('/' + config.get('kibana.index'), true);
|
||||
send('/' + config.get('kibana.index') + '/index-patterns', true);
|
||||
send('/' + config.get('kibana.index') + '/index-patterns/pattern-id', true);
|
||||
});
|
||||
|
||||
it('allows deleting kibana documents', function () {
|
||||
del('/' + config.get('kibana.index') + '/index-patterns', true);
|
||||
del('/' + config.get('kibana.index') + '/index-patterns/pattern-id', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('allows any destructive non-bulk requests against kibana index', function () {
|
||||
it('refresh', function () {
|
||||
send('/' + config.get('kibana.index') + '/_refresh', true);
|
||||
});
|
||||
|
||||
it('delete', function () {
|
||||
del('/' + config.get('kibana.index') + '/pasta/lasagna', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('assorted methods that are non-destructive', function () {
|
||||
it('validate', function () {
|
||||
run('GET', '/_search?search_type=count', true);
|
||||
run('GET', '/index/type/id', true);
|
||||
run('GET', '/index/type/_mapping/field/field1', true);
|
||||
run('GET', '/_aliases', true);
|
||||
run('GET', '/_nodes/', true);
|
||||
run('HEAD', '/', true);
|
||||
run('HEAD', '/' + config.get('kibana.index'), true);
|
||||
run('HEAD', '/other-index', true);
|
||||
run('GET', '/_cluster/health', true);
|
||||
run('POST', '/' + config.get('kibana.index') + '/__notRealIndex__/_validate/query?q=foo:bar', true);
|
||||
run('POST', '/_validate', true);
|
||||
run('POST', '/_search', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bulk indexing', function () {
|
||||
it('valid', function () {
|
||||
send('/_bulk', [
|
||||
{ create: { _index: config.get('kibana.index'), _type: 'index-pattern' } },
|
||||
{ fields: [] },
|
||||
{ create: { _index: config.get('kibana.index'), _type: 'vis' } },
|
||||
{ aggs: [] }
|
||||
], true);
|
||||
|
||||
send('/' + config.get('kibana.index') + '/_bulk', [
|
||||
// implicit index
|
||||
{ create: { _type: 'index-pattern' } },
|
||||
{ fields: [] },
|
||||
|
||||
// explicit index
|
||||
{ create: { _index: config.get('kibana.index'), _type: 'vis' } },
|
||||
{ aggs: [] }
|
||||
|
||||
], true);
|
||||
});
|
||||
|
||||
it('rejects bulks including even one other index', function () {
|
||||
send('/' + config.get('kibana.index') + '/_bulk', [
|
||||
// implicit index
|
||||
{ create: { _type: 'index-pattern' } },
|
||||
{ fields: [] },
|
||||
// explicit index
|
||||
{ create: { _index: 'app-data', _type: 'vis' } },
|
||||
{ aggs: [] }
|
||||
], false);
|
||||
});
|
||||
|
||||
it('rejects malformed bulk bodies', function () {
|
||||
send('/_bulk', '{}\n{ "_index": "john" }\n', false);
|
||||
send('/_bulk', '{}\n{}\n', false);
|
||||
send('/_bulk', '{ "field": "value" }', false);
|
||||
send('/_bulk', '{ "field": "v', false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('msearch', function () {
|
||||
it('requires a bulk-formatted body', function () {
|
||||
send('/_msearch', false);
|
||||
send('/_msearch', '{}', false);
|
||||
send('/_msearch', '{}\n{}\n', true);
|
||||
send('/_msearch', '{}\n{}\n{}\n', false);
|
||||
});
|
||||
|
||||
it('allows searching any index', function () {
|
||||
send('/app-index/_msearch', [
|
||||
{},
|
||||
{ query: { match_all: {} } }
|
||||
], true);
|
||||
|
||||
send('/app-index/data-type/_msearch', [
|
||||
{},
|
||||
{ query: { match_all: {} } }
|
||||
], true);
|
||||
|
||||
send('/_msearch', [
|
||||
{ _index: 'app-index', _type: 'data-type' },
|
||||
{ query: { match_all: {} } },
|
||||
{ _index: 'IT-index', _type: 'logs' },
|
||||
{ query: { match_all: {} } },
|
||||
{ _index: 'L33t', _type: '?' },
|
||||
{ query: { match_all: {} } },
|
||||
], true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mget', function () {
|
||||
it('requires a valid json body', function () {
|
||||
send('/_mget', false);
|
||||
send('/_mget', '{}', true);
|
||||
send('/_mget', '{}\n{}\n', false);
|
||||
});
|
||||
|
||||
it('allows reading from any index', function () {
|
||||
send('/app-index/_mget', { docs: { match_all: {} } }, true);
|
||||
send('/app-index/data-type/_mget', { docs: [ {} ] }, true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
135
test/unit/server/plugins/elasticsearch/version_math.js
Normal file
135
test/unit/server/plugins/elasticsearch/version_math.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
var root = require('requirefrom')('');
|
||||
var _ = require('lodash');
|
||||
var versionMath = root('src/hapi/plugins/elasticsearch/lib/version_math');
|
||||
var expect = require('expect.js');
|
||||
var versions = [
|
||||
'1.1.12',
|
||||
'1.1.12',
|
||||
'1.1.12',
|
||||
'1.1.12',
|
||||
'0.90.0',
|
||||
'0.90.1',
|
||||
'1.0.0',
|
||||
'1.0',
|
||||
'1.2.3',
|
||||
'2.0.0',
|
||||
'2.0.1',
|
||||
'2.3.1'
|
||||
];
|
||||
|
||||
describe('plugins/elasticsearch', function () {
|
||||
describe('lib/version_math', function () {
|
||||
describe('version math (0.90.0 - 2.3.1)', function () {
|
||||
var methods = 'max,min,eq,is,lt,lte,gt,gte'.split(',');
|
||||
describe('methods', function () {
|
||||
it('should have ' + methods.join(', ') + ' methods', function () {
|
||||
_.each(methods, function (method) {
|
||||
expect(versionMath[method]).to.be.a(Function);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('min & max', function () {
|
||||
it('has a max of 2.3.1', function () {
|
||||
expect(versionMath.max(versions)).to.be('2.3.1');
|
||||
});
|
||||
|
||||
it('has a min of 0.90.0', function () {
|
||||
expect(versionMath.min(versions)).to.be('0.90.0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('eq / lowest version', function () {
|
||||
it('should be true for 0.90.0', function () {
|
||||
expect(versionMath.eq('0.90.0', versions)).to.be(true);
|
||||
});
|
||||
|
||||
it('should be false for 1.0', function () {
|
||||
expect(versionMath.eq('1.0', versions)).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('gt / lowest version', function () {
|
||||
it('is > 0.20.3', function () {
|
||||
expect(versionMath.gt('0.20.3', versions)).to.be(true);
|
||||
});
|
||||
|
||||
it('is not > 0.90.0', function () {
|
||||
expect(versionMath.gt('0.90.0', versions)).to.be(false);
|
||||
});
|
||||
|
||||
it('is not > 1.0.0', function () {
|
||||
expect(versionMath.gt('1.0.0', versions)).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('gte / lowest version', function () {
|
||||
it('is >= 0.20.3', function () {
|
||||
expect(versionMath.gte('0.20.3', versions)).to.be(true);
|
||||
});
|
||||
|
||||
it('is >= 0.90.0', function () {
|
||||
expect(versionMath.gte('0.90.0', versions)).to.be(true);
|
||||
});
|
||||
|
||||
it('is not >= 1.0.0', function () {
|
||||
expect(versionMath.gte('1.0.0', versions)).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('lt / highest version', function () {
|
||||
it('is not < 0.20.3', function () {
|
||||
expect(versionMath.lt('0.20.3', versions)).to.be(false);
|
||||
});
|
||||
|
||||
it('is not < 2.3.1', function () {
|
||||
expect(versionMath.lt('2.3.1', versions)).to.be(false);
|
||||
});
|
||||
|
||||
it('is < 2.5', function () {
|
||||
expect(versionMath.lt('2.5', versions)).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('lte / highest version', function () {
|
||||
it('is not =< 0.20.3', function () {
|
||||
expect(versionMath.lte('0.20.3', versions)).to.be(false);
|
||||
});
|
||||
|
||||
it('is =< 2.3.1', function () {
|
||||
expect(versionMath.lte('2.3.1', versions)).to.be(true);
|
||||
});
|
||||
|
||||
it('is =< 2.5', function () {
|
||||
expect(versionMath.lte('2.5', versions)).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('is', function () {
|
||||
it('exactly, <, <=, >, >=', function () {
|
||||
expect(versionMath.is('0.90.0', versions)).to.be(true);
|
||||
expect(versionMath.is('0.20.0', versions)).to.be(false);
|
||||
|
||||
expect(versionMath.is('>0.20.0', versions)).to.be(true);
|
||||
expect(versionMath.is('>0.90.0', versions)).to.be(false);
|
||||
expect(versionMath.is('>0.90.1', versions)).to.be(false);
|
||||
|
||||
expect(versionMath.is('>=0.20.0', versions)).to.be(true);
|
||||
expect(versionMath.is('>=0.90.0', versions)).to.be(true);
|
||||
expect(versionMath.is('>=0.90.1', versions)).to.be(false);
|
||||
|
||||
expect(versionMath.is('<2.5', versions)).to.be(true);
|
||||
expect(versionMath.is('<2.3.1', versions)).to.be(false);
|
||||
expect(versionMath.is('<0.90.1', versions)).to.be(false);
|
||||
|
||||
expect(versionMath.is('<=2.5', versions)).to.be(true);
|
||||
expect(versionMath.is('<=2.3.1', versions)).to.be(true);
|
||||
expect(versionMath.is('<=0.90.1', versions)).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue