Slight refactor to the api module, so it will simply extend the client like it did

This commit is contained in:
Spencer Alger
2013-10-23 14:49:00 -07:00
parent 35209ea61a
commit c14d37aa42
39 changed files with 25589 additions and 3627 deletions

View File

@ -23,19 +23,28 @@ module.exports = function (grunt) {
options: {
colors: true,
require: 'should',
reporter: 'dot'
reporter: 'dot',
bail: true,
timeout: 11000
}
},
jshint: {
source: {
src: [
'src/**/*.js',
'test/**/*.js',
'Gruntfile.js'
]
],
options: {
jshintrc: '.jshintrc'
}
},
options: {
jshintrc: true
tests: {
src: [
'test/**/*.js'
],
options: {
jshintrc: 'test/.jshintrc'
}
}
},
watch: {
@ -52,6 +61,14 @@ module.exports = function (grunt) {
options: {
interupt: true
}
},
run: {
generate_js_api: {
cmd: 'node',
args: [
'scripts/generate/js_api/index.js'
]
}
}//,
// docular: {
// groups: [
@ -100,10 +117,27 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-jshint');
// Default task.
// grunt.registerTask('docs', ['docular']);
grunt.registerTask('test', ['jshint', 'mochaTest']);
grunt.registerTask('default', ['jshint', 'mochaTest:unit']);
grunt.task.registerMultiTask('run', 'used to run arbitrary commands', function () {
var done = this.async();
var proc = require('child_process').spawn(
this.data.cmd,
this.data.args,
{
stdio: ['ignore', 'pipe', 'pipe']
}
);
proc.stdout.on('data', grunt.log.write);
proc.stderr.on('data', grunt.log.error);
proc.on('close', function (exitCode) {
done(!exitCode);
});
});
};

View File

@ -24,7 +24,8 @@
"grunt-contrib-watch": "~0.5.3",
"expect.js": "~0.2.0",
"async": "~0.2.9",
"optimist": "~0.6.0"
"optimist": "~0.6.0",
"minimatch": "~0.2.12"
},
"license": "Apache License",
"dependencies": {

View File

@ -4,30 +4,48 @@ var path = require('path');
var fs = require('fs');
var mkdirp = require('mkdirp');
var outputDir = _.joinPath(__dirname, '../../../src/api/');
var outputPath = _.joinPath(__dirname, '../../../src/lib/api.js');
var templates = require('./templates');
var specs = require('./spec')(outputDir);
var specs = require('./spec');
// completely delete the output directory
function clean(path) {
if (fs.existsSync(path)) {
var clean = (function () {
function rmDirRecursive(path) {
fs.readdirSync(path).forEach(function (file, index) {
var curPath = path + '/' + file;
if (fs.statSync(curPath).isDirectory()) { // recurse
clean(curPath);
rmDirRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
}
return function (path) {
try {
var stats = fs.statSync(path);
if (stats && stats.isDirectory()) {
console.log('removing', path, 'directory recursively');
rmDirRecursive(path);
} else {
console.log('removing', path);
fs.unlinkSync(path);
}
return true;
} catch (e) {
return false;
}
};
})();
exports.run = function () {
var defs = [];
var namespaces = [];
clean(outputPath);
var actions = _.map(specs, function (spec) {
spec.urls = _.map(
_.sortBy(
@ -67,9 +85,9 @@ exports.run = function () {
});
var docUrl = spec.docUrl;
var location = _.map(spec.name.split('.'), _.camelCase).join('.');
spec = _.pick(spec, [
'name',
'methods',
'params',
'urls',
@ -85,7 +103,6 @@ exports.run = function () {
]);
}, {});
var location = _.map(spec.name.split('.'), _.camelCase).join('.');
if (~location.indexOf('.')) {
var steps = location.split('.');
namespaces.push(steps.slice(0, -1).join('.'));
@ -94,27 +111,18 @@ exports.run = function () {
// escape method names with "special" keywords
location = location.replace(/(^|\.)(delete|default)(\.|$)/g, '[\'$2\']');
return templates.clientAction({spec: spec, location: location, docUrl: docUrl });
return {
spec: spec,
location: location,
docUrl: docUrl
};
});
namespaces = _.map(_.unique(namespaces.sort(), true), function (namespace) {
return templates.clientActionNamespace({
get: namespace,
set: namespace.replace(/\./g, '.prototype.'),
});
})
var l = templates.lines(0);
l('var ClientAction = require(\'./client_action\');');
l('var errors = require(\'./errors\');');
l('');
l('exports.attach = function (Client) {').in();
l.split(namespaces.join('') + '\n' + actions.join('\n'));
l.out('};');
fs.writeFileSync(_.joinPath(__dirname, '../../../src/lib/api.js'), l.toString());
console.log('writing', actions.length, 'api actions to', outputPath);
fs.writeFileSync(outputPath, templates.apiFile({
actions: actions,
namespaces: _.unique(namespaces.sort(), true)
}));
};
exports.run();

View File

@ -0,0 +1,48 @@
var _ = require('../../../src/lib/utils')
var docs = _.requireDir(module, '../../../es_api_spec/api');
var aliases = require('./aliases');
var castNotFoundRE = /exists/;
var usesBulkBodyRE = /^(bulk|msearch)$/;
var defs = [];
// itterate all of the found docs
Object.keys(docs).forEach(function (filename) {
Object.keys(docs[filename]).forEach(function (name) {
var def = docs[filename][name];
def.name = name;
defs.push(def);
})
});
module.exports = _.map(defs, function (def) {
var name = def.name;
var steps = name.split('.');
var spec = {
name: name,
methods: _.map(def.methods, function (m) { return m.toUpperCase(); }),
docUrl: def.documentation,
urlParts: def.url.parts,
params: def.url.params,
urls: _.difference(def.url.paths, aliases[name]),
body: def.body || null,
path2lib: _.repeat('../', steps.length + 1) + 'lib/'
};
if (def.body && def.body.requires) {
spec.needBody = true;
}
if (usesBulkBodyRE.test(name)) {
spec.bulkBody = true;
}
if (castNotFoundRE.test(name)) {
spec.castNotFound = true;
}
return spec;
});

View File

@ -0,0 +1,27 @@
var ca = require('./client_action').create;
var errors = require('./errors');
var api = module.exports = {};
api._namespaces = <%= stringify(namespaces) %>;<%
_.each(actions, function (action) {
var namespace = action.location.split('.').shift();
if (_.contains(namespaces, namespace)) {
_.pull(namespaces, namespace);
var className = _.studlyCase(namespace) + 'NS';
%>
api.<%= namespace %> = function <%= className %>(client) {
if (this instanceof <%= className %>) {
this.client = client;
} else {
return new <%= className %>(client);
}
};<%
}
%>
<%= partials.client_action(action) %><%
}); %>

View File

@ -9,4 +9,4 @@ _.each(spec.params, function(param, paramName) { %>
}
%><% }) %>
*/
Client.prototype<%= (location[0] === '[' ? '' : '.') + location %> = ClientAction(<%= stringify(spec, true) %>);
api<%= (location[0] === '[' ? '' : '.') + location %> = ca(<%= stringify(spec, true) %>);

View File

@ -268,7 +268,9 @@ var templateGlobals = {
l('this.client.request(request, cb);');
}
return l.toString();
}
},
partials: templates
};
fs.readdirSync(path.resolve(__dirname)).forEach(function (filename) {
@ -288,9 +290,6 @@ fs.readdirSync(path.resolve(__dirname)).forEach(function (filename) {
templates.text = templates.string;
module.exports = {
lines: lines,
action: templates.action,
clientAction: templates.client_action,
clientActionNamespace: templates.client_action_namespace,
apiFile: templates.api_file,
urlParamRE: urlParamRE
};

View File

@ -32,9 +32,10 @@ module.exports = Client;
var _ = require('./utils');
var ClientConfig = require('./client_config');
// var api = _.reKey(_.requireDir(module, '../api'), _.camelCase);
var ca = require('./client_action').create;
var q = require('q');
var errors = require('./errors');
var api = require('./api.js');
function Client(config) {
this.client = this;
@ -48,11 +49,13 @@ function Client(config) {
});
this.config.client = this;
for (var i = 0; i < _namespaces.length; i++) {
this[_namespaces[i]] = new this[_namespaces[i]](this);
for (var i = 0; i < this._namespaces.length; i++) {
this[this._namespaces[i]] = new this[this._namespaces[i]](this);
}
}
Client.prototype = api;
/**
* Perform a request with the client's transport
*
@ -91,7 +94,7 @@ Client.prototype.request = function (params, cb) {
}
if (params.body && params.method === 'GET') {
_.nextTick(cb, new TypeError('Body can not be sent with method "GET"'));
respond(new TypeError('Body can not be sent with method "GET"'));
return;
}
@ -164,12 +167,13 @@ Client.prototype.request = function (params, cb) {
* @param {Object} params - Currently just a placeholder, no params used at this time
* @param {Function} cb - callback
*/
Client.prototype.ping = function (params, cb) {
this.request({
method: 'HEAD',
path: '/'
}, cb);
};
Client.prototype.ping = ca({
methods: ['HEAD'],
params: {},
url: {
fmt: '/'
}
});
/**
* Ask an ES node for a list of all the nodes, add/remove nodes from the connection
@ -193,26 +197,14 @@ Client.prototype.sniff = function (cb) {
}
cb(err, resp);
});
}
var _namespaces = [];
/**
* These names of the properties that hold namespace objects in the Client prototype
* @type {Array}
*/
Client.namespace = function (namespace) {
var steps = namespace.split('.');
var path = [];
var on = Client;
var i;
for (i = 0; i < steps.length; i ++) {
path.push(steps[i]);
_namespaces.push(path.join('.'));
on.prototype[steps[i]] = function ClientActionNamespace(client) {
this.client = client;
};
}
};
require('./api.js').attach(Client);
/**
* Shutdown the connections, log outputs, and clear timers
*/
Client.prototype.close = function () {
this.config.log.close();
this.config.connectionPool.close();
};

View File

@ -51,6 +51,15 @@ function Log(config) {
}
_.inherits(Log, EventEmitter);
Log.prototype.close = function () {
this.emit('closing');
if (EventEmitter.listenerCount(this)) {
console.error('Something is still listening for log events, but the logger is closing.');
this.clearAllListeners();
}
}
/**
* Levels observed by the loggers, ordered by rank
*

File diff suppressed because it is too large Load Diff

View File

@ -32,9 +32,10 @@ module.exports = Client;
var _ = require('./utils');
var ClientConfig = require('./client_config');
// var api = _.reKey(_.requireDir(module, '../api'), _.camelCase);
var ca = require('./client_action').create;
var q = require('q');
var errors = require('./errors');
var api = require('./api.js');
function Client(config) {
this.client = this;
@ -48,11 +49,13 @@ function Client(config) {
});
this.config.client = this;
for (var i = 0; i < _namespaces.length; i++) {
this[_namespaces[i]] = new this[_namespaces[i]](this);
for (var i = 0; i < this._namespaces.length; i++) {
this[this._namespaces[i]] = new this[this._namespaces[i]](this);
}
}
Client.prototype = api;
/**
* Perform a request with the client's transport
*
@ -91,7 +94,7 @@ Client.prototype.request = function (params, cb) {
}
if (params.body && params.method === 'GET') {
_.nextTick(cb, new TypeError('Body can not be sent with method "GET"'));
respond(new TypeError('Body can not be sent with method "GET"'));
return;
}
@ -164,12 +167,13 @@ Client.prototype.request = function (params, cb) {
* @param {Object} params - Currently just a placeholder, no params used at this time
* @param {Function} cb - callback
*/
Client.prototype.ping = function (params, cb) {
this.request({
method: 'HEAD',
path: '/'
}, cb);
};
Client.prototype.ping = ca({
methods: ['HEAD'],
params: {},
url: {
fmt: '/'
}
});
/**
* Ask an ES node for a list of all the nodes, add/remove nodes from the connection
@ -193,26 +197,14 @@ Client.prototype.sniff = function (cb) {
}
cb(err, resp);
});
}
var _namespaces = [];
/**
* These names of the properties that hold namespace objects in the Client prototype
* @type {Array}
*/
Client.namespace = function (namespace) {
var steps = namespace.split('.');
var path = [];
var on = Client;
var i;
for (i = 0; i < steps.length; i ++) {
path.push(steps[i]);
_namespaces.push(path.join('.'));
on.prototype[steps[i]] = function ClientActionNamespace(client) {
this.client = client;
};
}
};
require('./api.js').attach(Client);
/**
* Shutdown the connections, log outputs, and clear timers
*/
Client.prototype.close = function () {
this.config.log.close();
this.config.connectionPool.close();
};

View File

@ -2,10 +2,10 @@
* Constructs a function that can be called to make a request to ES
* @type {[type]}
*/
module.exports = function clientAction(spec) {
exports.create = function clientAction(spec) {
return function (params, cb) {
return exec(this.client, spec, params, cb);
}
};
};
var errors = require('./errors');
@ -75,8 +75,8 @@ var castType = {
}
};
function resolveUrl (url, params) {
var vars = {}, name, i, key;
function resolveUrl(url, params) {
var vars = {}, i, key;
if (url.req) {
// url has required params
@ -128,7 +128,7 @@ function resolveUrl (url, params) {
// remove it from the params so that it isn't sent to the final request
delete params[name];
}, {}));
};
}
function exec(client, spec, params, cb) {
if (typeof params === 'function') {
@ -139,20 +139,25 @@ function exec(client, spec, params, cb) {
cb = typeof cb === 'function' ? cb : _.noop;
}
var request = {
ignore: params.ignore
};
var request = {};
var parts = {};
var query = {};
var i;
if (spec.needsBody && !params.body) {
return _.nextTick(cb, new TyperError(spec.name + ' requires a request body.'));
return _.nextTick(cb, new TypeError('A request body is required.'));
}
if (params.body) {
request.body = params.body;
request.bulkBody = spec.bulkBody;
}
if (spec.bulkBody) {
request.bulkBody = true;
}
if (params.ignore) {
request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore];
}
if (spec.methods.length === 1) {
@ -238,4 +243,4 @@ function exec(client, spec, params, cb) {
} else {
client.request(request, cb);
}
};
}

View File

@ -94,7 +94,7 @@ ClientConfig.prototype.prepareHosts = function (hosts) {
hosts = [hosts];
}
for(i = 0; i < hosts.length; i++) {
for (i = 0; i < hosts.length; i++) {
host = hosts[i];
if (typeof host === 'object') {
if (host.protocol) {

View File

@ -54,11 +54,13 @@ ConnectionAbstract.prototype.setStatus = function (status) {
this.status = status;
if (status === 'dead') {
if (status === 'dead' || status === 'closed') {
if (this.__deadTimeout) {
clearTimeout(this.__deadTimeout);
}
this.__deadTimeout = setTimeout(this.bound.resuscitate, this.config.deadTimeout);
if (status === 'dead') {
this.__deadTimeout = setTimeout(this.bound.resuscitate, this.config.deadTimeout);
}
}
this.emit('status changed', status, origStatus, this);

View File

@ -93,13 +93,15 @@ ConnectionPool.prototype._remove = function (connection) {
connection.setStatus('closed');
connection.removeListener('status changed', this.bound.onStatusChanged);
}
}
};
ConnectionPool.prototype.setNodes = function (nodeConfigs) {
var i;
var connection;
var i;
var id;
var node;
var toRemove = _.clone(this.index);
for (i = 0; i < nodeConfigs.length; i++) {
node = nodeConfigs[i];
if (node.hostname && node.port) {
@ -115,9 +117,9 @@ ConnectionPool.prototype.setNodes = function (nodeConfigs) {
}
_.each(toRemove, this._remove, this);
}
};
ConnectionPool.prototype.empty = function () {
ConnectionPool.prototype.close = function () {
this.setNodes([]);
};
ConnectionPool.prototype.empty = ConnectionPool.prototype.close;

View File

@ -70,8 +70,6 @@ HttpConnection.prototype.request = function (params, cb) {
headers: _.defaults(params.headers || {}, defaultHeaders)
});
log.debug('starting request', requestId);
// general clean-up procedure to run after the request, can only run once
var cleanUp = function (err) {
clearTimeout(timeoutId);
@ -80,7 +78,7 @@ HttpConnection.prototype.request = function (params, cb) {
incoming && incoming.removeAllListeners();
log.debug('calling back request', requestId, err ? 'with error "' + err.message + '"' : '');
_.nextTick(cb, err, reqParams, response, status);
cb(err, reqParams, response, status);
// override so this doesn't get called again
cleanUp = _.noop;
@ -88,9 +86,7 @@ HttpConnection.prototype.request = function (params, cb) {
reqParams.agent = this.agent;
request = http.request(reqParams);
request.on('response', function (_incoming) {
request = http.request(reqParams, function (_incoming) {
incoming = _incoming;
status = incoming.statusCode;
incoming.setEncoding('utf8');

View File

@ -51,6 +51,15 @@ function Log(config) {
}
_.inherits(Log, EventEmitter);
Log.prototype.close = function () {
this.emit('closing');
if (EventEmitter.listenerCount(this)) {
console.error('Something is still listening for log events, but the logger is closing.');
this.clearAllListeners();
}
}
/**
* Levels observed by the loggers, ordered by rank
*

View File

@ -85,7 +85,7 @@ LoggerAbstract.prototype.setupListeners = function (levels) {
*/
LoggerAbstract.prototype.cleanUpListeners = _.handler(function () {
_.each(this.listeningLevels, function (level) {
this.bridge.removeListener(level, this.handlers[level]);
this.bridge.removeListener(level, this.bound['on' + _.ucfirst(level)]);
}, this);
});

View File

@ -295,7 +295,7 @@ utils.inherits = function (constructor, superConstructor) {
* @returns {String}
*/
utils.trim = function (str) {
return typeof str !== 'string' ? str.replace(/^\s+|\s+$/g, '') : '';
return typeof str === 'string' ? str.replace(/^\s+|\s+$/g, '') : '';
};
utils.collectMatches = function (text, regExp) {
@ -385,8 +385,13 @@ utils.applyArgs = function (func, context, args, sliceIndex) {
* @return {[type]} [description]
*/
_.nextTick = function (cb) {
console.log('tick');
var args = Array.prototype.slice.call(arguments, 1);
// bind the function and schedule it
process.nextTick(_.bindKey(_, 'applyArgs', cb, null, arguments, 1));
process.nextTick(function () {
console.log('tock');
cb.apply(null, args);
});
};
/**

View File

@ -1,2 +0,0 @@
// exports['cluster.node_info'] =
// '//TODO: this enpoint ***needs*** work, many of the possible urls are not supported';

View File

@ -1,54 +0,0 @@
var _ = require('../../../src/lib/utils')
var docs = _.requireDir(module, '../../../es_api_spec/api');
var aliases = require('./aliases');
var notes = require('./notes');
var castNotFoundRE = /exists/;
var usesBulkBodyRE = /^(bulk|msearch)$/;
var defs = [];
// itterate all of the found docs
Object.keys(docs).forEach(function (filename) {
Object.keys(docs[filename]).forEach(function (name) {
var def = docs[filename][name];
def.name = name;
defs.push(def);
})
});
module.exports = function (outputDir) {
return _.map(defs, function (def) {
var name = def.name;
var steps = name.split('.');
var spec = {
fileName: steps.pop() + '.js',
dirName: _.joinPath(outputDir, steps.join('/') || './'),
name: name,
methods: _.map(def.methods, function (m) { return m.toUpperCase(); }),
docUrl: def.documentation,
urlParts: def.url.parts,
params: def.url.params,
urls: _.difference(def.url.paths, aliases[name]),
body: def.body || null,
path2lib: _.repeat('../', steps.length + 1) + 'lib/',
notes: notes[name],
};
if (def.body && def.body.requires) {
spec.needBody = true;
}
if (usesBulkBodyRE.test(name)) {
spec.bulkBody = true;
}
if (castNotFoundRE.test(name)) {
spec.castNotFound = true;
}
return spec;
});
};

View File

@ -1 +0,0 @@
<%= set %> = <%= get %>;

View File

@ -1,7 +0,0 @@
if (<%= get %>.toLowerCase && (<%= get %> = <%= get %>.toLowerCase())
&& (<%= get %> === 'no' || <%= get %> === 'off')
) {
<%= set %> = false;
} else {
<%= set %> = !!<%= get %>;
}

View File

@ -1 +0,0 @@
Client.namespace(<%= stringify(get) %>);

View File

@ -1,5 +0,0 @@
if (_.isNumeric(<%= get %>) || _.isInterval(<%= get %>)) {
<%= set %> = <%= get %>;
} else {
throw new TypeError('Invalid <%= name %>: ' + <%= get %> + ' should be a number or in interval notation (an integer followed by one of Mwdhmsy).');
}

View File

@ -1,8 +0,0 @@
if (_.contains(<%= _.camelCase(name) %>Options, <%= get %>)) {
<%= set %> = <%= get %>;
} else {
throw new TypeError(
'Invalid <%= name %>: ' + <%= get %> +
' should be one of ' + <%= _.camelCase(name) %>Options.join(', ') + '.'
);
}

View File

@ -1,14 +0,0 @@
switch (typeof <%= get %>) {
case 'string':
<%= set %> = <%= get %>;
break;
case 'object':
if (_.isArray(<%= get %>)) {
<%= set %> = <%= get %>.join(',');
} else {
throw new TypeError('Invalid <%= name %>: ' + <%= get %> + ' should be a comma seperated list, array, or boolean.');
}
break;
default:
<%= set %> = !!<%= get %>;
}

View File

@ -1,5 +0,0 @@
if (_.isNumeric(<%= get %>)) {
<%= set %> = <%= get %> * 1;
} else {
throw new TypeError('Invalid <%= name %>: ' + <%= get %> + ' should be a number.');
}

View File

@ -1,5 +0,0 @@
if (typeof <%= get %> !== 'object' && <%= get %>) {
<%= set %> = '' + <%= get %>;
} else {
throw new TypeError('Invalid <%= name %>: ' + <%= get %> + ' should be a string.');
}

View File

@ -1,7 +0,0 @@
if (<%= get %> instanceof Date) {
<%= set %> = <%= get %>.getTime();
} else if (_.isNumeric(<%= get %>)) {
<%= set %> = <%= get %>;
} else {
throw new TypeError('Invalid <%= name %>: ' + <%= get %> + ' should be be some sort of time.');
}

View File

@ -5,23 +5,25 @@ var path = require('path'),
expect = require('expect.js'),
server = require('./server'),
_ = require('../../../src/lib/utils'),
es = require('../../../src/elasticsearch');
es = require('../../../src/elasticsearch'),
Minimatch = require('minimatch').Minimatch;
var argv = require('optimist')
.default('executable', path.join(process.env.ES_HOME, './bin/elasticsearch'))
.default('clusterName', 'yaml-test-runner')
.default('dataPath', '/tmp/yaml-test-runner')
.default('hostname', 'localhost')
.default('port', '9200')
.default('match', '**')
.boolean('createServer')
.argv;
// if (argv.hostname || argv.port) {
// console.log('working with ES instance at ' + argv.hostname + ':' + argv.port);
// }
Error.stackTraceLimit = Infinity;
// Where do the tests live?
var TEST_DIR = path.resolve(__dirname, '../../../es_api_spec/test/');
// test names matching this will be run
var doRE = /(^|\/)(.*)\/.*/;
var doPattern = new Minimatch(argv.match);
// a reference to a personal instance of ES Server
var esServer = null;
@ -40,17 +42,49 @@ function clearIndices(done) {
}, done);
}
function createClient() {
if (client) {
client.close();
}
client = new es.Client({
hosts: [
{
hostname: esServer ? esServer.__hostname : argv.hostname,
port: esServer ? esServer.__port : argv.port
}
],
// log: null
log: {
type: 'file',
level: 'trace',
path: logFile
}
});
}
function createServer(done) {
server.start(argv, function (err, server) {
esServer = server;
done(err);
});
}
// before running any tests...
before(function (done) {
// start our personal ES Server
this.timeout(null);
if (argv.hostname) {
done();
if (argv.createServer) {
createServer(done);
} else {
server.start(argv, function (err, server) {
esServer = server;
done(err);
});
createClient();
client.ping(function (err) {
if (err) {
createServer(done);
} else {
done();
}
})
}
});
@ -66,22 +100,7 @@ before(function (done) {
});
before(function () {
Error.stackTraceLimit = Infinity;
// create the client
client = new es.Client({
hosts: [
{
hostname: esServer ? esServer.__hostname : argv.hostname,
port: esServer ? esServer.__port : argv.port
}
],
log: null
// log: {
// type: 'file',
// level: ['error', 'warning', 'trace'],
// path: logFile
// }
});
createClient();
});
before(clearIndices);
@ -97,7 +116,7 @@ function loadDir(dir) {
var location = path.join(dir, fileName),
stat = fs.statSync(location);
if (stat.isFile() && fileName.match(/\.yaml$/) && location.match(doRE)) {
if (stat.isFile() && fileName.match(/\.yaml$/) && doPattern.match(path.relative(TEST_DIR, location))) {
loadFile(location);
}
else if (stat.isDirectory()) {
@ -188,25 +207,21 @@ function rangeMatchesCurrentVersion(rangeString, done) {
}
/**
* read the file's contents, parse the yaml, pass to makeTest
* read the file's contents, parse the yaml, pass to makeTestFromYamlDoc
*
* @param {String} path - Full path to yaml file
* @return {undefined}
*/
function loadFile(location) {
var docsInFile = [];
jsYaml.loadAll(
fs.readFileSync(location, { encoding: 'utf8' }),
function (testConfig) {
docsInFile.push(testConfig);
function (doc) {
makeTestFromYamlDoc(doc);
},
{
filename: location
}
);
_.each(docsInFile, makeTest);
}
/**
@ -217,15 +232,15 @@ function loadFile(location) {
* @param {Object} testConfigs - The yaml document
* @return {undefined}
*/
function makeTest(testConfig, count) {
function makeTestFromYamlDoc(yamlDoc, count) {
var setup;
if (_.has(testConfig, 'setup')) {
(new ActionRunner(testConfig.setup)).each(function (action, name) {
if (_.has(yamlDoc, 'setup')) {
(new ActionRunner(yamlDoc.setup)).each(function (action, name) {
before(action);
});
delete testConfig.setup;
delete yamlDoc.setup;
}
_.forOwn(testConfig, function (test, description) {
_.forOwn(yamlDoc, function (test, description) {
describe(description, function () {
var actions = new ActionRunner(test);
actions.each(function (action, name) {
@ -462,21 +477,23 @@ ActionRunner.prototype = {
if (catcher instanceof RegExp) {
// error message should match the regexp
expect(error.message).to.match(catcher);
error = null;
} else if (typeof catcher === 'function') {
// error should be an instance of
expect(error).to.be.a(catcher);
error = null;
} else {
throw new Error('Invalid catcher ' + catcher);
return done(new Error('Invalid catcher ' + catcher));
}
} else {
throw error;
return done(error);
}
}
done();
done(error);
}, this));
} else {
throw new Error('stepped in do_do, did not find a function');
done(new Error('stepped in do_do, did not find a function'));
}
},

File diff suppressed because it is too large Load Diff

View File

@ -15,12 +15,12 @@ exports.start = function (params, cb) {
params.executable,
[
'-f',
'-D es.cluster.name=' + params.clusterName,
params.port ? '-D es.http.port=' + params.port : undefined,
'-D es.path.data=' + params.dataPath,
'-D es.gateway.type=none',
'-D es.index.store.type=memory',
'-D es.discovery.zen.ping.multicast.enabled=false',
'-Des.cluster.name=' + params.clusterName,
'-Des.path.data=' + params.dataPath,
'-Des.logger.level=DEBUG',
'-Des.gateway.type=none',
'-Des.index.store.type=memory',
'-Des.discovery.zen.ping.multicast.enabled=false',
],
{
cwd: undefined,
@ -34,15 +34,14 @@ exports.start = function (params, cb) {
);
server.stdout.on('data', function (line) {
line = line.toString();
line = _.trim(line.toString());
var match;
// console.log(_.trim(line));
if (!params.port && (match = line.match(/bound_address \{inet\[\/?([^:]+):(\d+)\]\}/))) {
if (match = line.match(/bound_address \{inet\[\/?([^:]+):(\d+)\]\}/)) {
server.__hostname = match[1];
server.__port = match[2];
}
if (line.match(/started\s*$/)) {
if (line.match(/started\s*$/m)) {
console.log('Personal ES Server started at', server.__hostname + ':' + server.__port);
server.stdout.removeAllListeners();
server.stderr.removeAllListeners();
@ -51,9 +50,13 @@ exports.start = function (params, cb) {
});
server.stderr.on('data', function (line) {
console.error(_.trim(line));
console.error(_.trim(line.toString()));
});
server.on('exit', function (code) {
console.log('Personal ES Server Shutdown with exit code', code);
})
process.on('exit', function () {
server.kill();
});

View File

@ -1,2 +1,3 @@
--require should
--reporter dot
--timeout 11000

View File

@ -1,5 +1,5 @@
var es = require('../../src/elasticsearch'),
api = require('../../src/lib/utils').requireDir(module, '../../src/api'),
api = require('../../src/lib/api'),
expect = require('expect.js');
describe('Client instances creation', function () {
@ -10,7 +10,7 @@ describe('Client instances creation', function () {
});
it('inherits the api', function () {
client.bulk.should.be.exactly(api.bulk);
client.cluster.nodeStats.should.be.exactly(api.cluster.node_stats);
client.bulk.should.eql(api.bulk);
client.cluster.nodeStats.should.eql(api.cluster.prototype.nodeStats);
});
});

View File

@ -1,45 +0,0 @@
var es = require('../../src/elasticsearch'),
sinon = require('sinon'),
expect = require('expect.js');
describe('transport', function () {
describe('#sniff', function () {
it('does a head request to "/"', function (done) {
var c = new es.Client();
// stub the tranports request method, arg 1 is a callback
sinon.stub(c.transport, 'request').callsArgAsync(1);
c.transport.sniff(function (err, resp) {
var spy = c.transport.request.getCall(0),
params = spy.args[0];
params.should.have.type('object');
params.should.have.property('path', '/_cluster/nodes');
if (params.method) {
params.should.be('GET');
}
done();
});
});
describe('when sniffOnStart === true', function () {
describe('and the cluster is down', function () {
before(function (done) {
var c = new es.Client({
sniffOnStart: true,
hosts: [
'intentionally-not-a-real-cluster.com:9200'
]
});
c.on('sniff complete', done);
});
it('should not have any connections in the connection pool', function () {
});
});
});
});
});

View File

@ -114,25 +114,6 @@ describe('Utils', function () {
});
describe('Lodash Modifications', function () {
describe('#map', function () {
it('returns an object when passed an object', function () {
var out = _.map({a: 1, b: 2}, function (val) { return val * 2; });
expect(out).to.eql({a: 2, b: 4});
});
it('returns an array for anything else', function () {
var std = _.map([1, 2, 3], function (val) { return val * 2; });
expect(std)
.to.be.a('array')
.and.to.eql(_.map('123', function (val) { return val * 2; }));
});
});
});
describe('String Transformers', function () {
describe('#camelCase', function () {