Added a quiet cli option to the plugin installer, reworked settingParser to clean up scope

This commit is contained in:
Jim Unger 2015-07-15 16:17:27 -05:00
parent 7a37dcf71d
commit 49d1e5a176
8 changed files with 207 additions and 180 deletions

View file

@ -35,7 +35,9 @@ module.exports = function (grunt) {
'Gruntfile.js',
'<%= root %>/tasks/**/*.js',
'<%= src %>/kibana/*.js',
'<%= src %>/server/**/*.js',
'<%= src %>/server/bin/*.js',
'<%= src %>/server/{config,lib,plugins}/**/*.js',
'<%= src %>/server/bin/{plugin,startup}/**/*.js',
'<%= src %>/kibana/{components,directives,factories,filters,plugins,registry,services,utils}/**/*.js',
'<%= unitTestDir %>/**/*.js',
'!<%= unitTestDir %>/specs/vislib/fixture/**/*'

View file

@ -31,7 +31,6 @@
"scripts": {
"test": "grunt test",
"start": "node ./src/server/bin/kibana.js",
"postinstall": "bower install && grunt licenses --check-validity",
"precommit": "grunt lintStagedFiles"
},
"repository": {

View file

@ -7,14 +7,14 @@ module.exports = function (program) {
function processCommand(command, options) {
var settings;
try {
settings = settingParser.parse(command);
settings = settingParser(command).parse();
} catch (ex) {
//The logger has not yet been initialized.
console.error(ex.message);
process.exit(64);
}
var logger = pluginLogger(settings.silent);
var logger = pluginLogger(settings);
if (settings.action === 'install') {
installer.install(settings, logger);
@ -32,7 +32,7 @@ module.exports = function (program) {
'\t https://download.elastic.co/username/sample/sample-latest.tar.gz\n' +
'\t https://github.com/username/sample/archive/master.tar.gz\n\n' +
'\t -i username/sample/v1.1.1\n' +
'\t attempts to download from the following urls:\n' +
'\t attempts to download version v1.1.1 from the following urls:\n' +
'\t https://download.elastic.co/username/sample/sample-v1.1.1.tar.gz\n' +
'\t https://github.com/username/sample/archive/v1.1.1.tar.gz\n\n' +
'\t -i sample -u http://www.example.com/other_name.tar.gz\n' +
@ -45,7 +45,8 @@ module.exports = function (program) {
.description('Maintain Plugins')
.option('-i, --install <org>/<plugin>/<version>', installDesc)
.option('-r, --remove <plugin>', 'The plugin to remove')
.option('-s, --silent', 'Disable process messaging')
.option('-q, --quiet', 'Disable all process messaging except errors')
.option('-s, --silent', 'Disable all process messaging')
.option('-u, --url <url>', 'Specify download url')
.option('-t, --timeout <duration>', 'Length of time before failing; 0 for never fail', settingParser.parseMilliseconds)
.action(processCommand);

View file

@ -1,9 +1,10 @@
module.exports = function (silent) {
module.exports = function (settings) {
var previousLineEnded = true;
silent = !!silent;
var silent = !!settings.silent;
var quiet = !!settings.quiet;
function log(data, sameLine) {
if (silent) return;
if (silent || quiet) return;
if (!sameLine && !previousLineEnded) {
process.stdout.write('\n');

View file

@ -1,101 +1,108 @@
var path = require('path');
var expiry = require('expiry-js');
module.exports = {
parse: parse,
parseMilliseconds: parseMilliseconds
};
module.exports = function (options) {
function parseMilliseconds(val) {
var result;
function parseMilliseconds(val) {
var result;
try {
var timeVal = expiry(val);
result = timeVal.asMilliseconds();
} catch (ex) {
result = 0;
}
try {
var timeVal = expiry(val);
result = timeVal.asMilliseconds();
} catch (ex) {
result = 0;
return result;
}
return result;
}
function generateDownloadUrl(settings) {
var version = (settings.version) || 'latest';
var filename = settings.package + '-' + version + '.tar.gz';
function generateDownloadUrl(settings) {
var version = (settings.version) || 'latest';
var filename = settings.package + '-' + version + '.tar.gz';
return 'https://download.elastic.co/' + settings.organization + '/' + settings.package + '/' + filename;
}
function generateGithubUrl(settings) {
var version = (settings.version) || 'master';
var filename = version + '.tar.gz';
return 'https://github.com/' + settings.organization + '/' + settings.package + '/archive/' + filename;
}
function parse(options) {
var parts;
var settings = {
timeout: 0,
silent: false,
urls: []
};
settings.workingPath = path.resolve(__dirname, '..', 'plugins', '.plugin.installing');
if (options.timeout) {
settings.timeout = options.timeout;
return 'https://download.elastic.co/' + settings.organization + '/' + settings.package + '/' + filename;
}
if (options.silent) {
settings.silent = options.silent;
function generateGithubUrl(settings) {
var version = (settings.version) || 'master';
var filename = version + '.tar.gz';
return 'https://github.com/' + settings.organization + '/' + settings.package + '/archive/' + filename;
}
if (options.url) {
settings.urls.push(options.url);
}
function parse() {
var parts;
var settings = {
timeout: 0,
silent: false,
quiet: false,
urls: []
};
if (options.install) {
settings.action = 'install';
parts = options.install.split('/');
settings.workingPath = path.resolve(__dirname, '..', 'plugins', '.plugin.installing');
if (options.timeout) {
settings.timeout = options.timeout;
}
if (options.parent && options.parent.quiet) {
settings.quiet = options.parent.quiet;
}
if (options.silent) {
settings.silent = options.silent;
}
if (options.url) {
settings.urls.push(options.url);
}
if (options.install) {
settings.action = 'install';
parts = options.install.split('/');
if (options.url) {
if (parts.length !== 1) {
throw new Error('Invalid install option. When providing a url, please use the format <plugin>.');
}
settings.package = parts.shift();
} else {
if (parts.length < 2 || parts.length > 3) {
throw new Error('Invalid install option. Please use the format <org>/<plugin>/<version>.');
}
settings.organization = parts.shift();
settings.package = parts.shift();
settings.version = parts.shift();
settings.urls.push(generateDownloadUrl(settings));
settings.urls.push(generateGithubUrl(settings));
}
}
if (options.remove) {
settings.action = 'remove';
parts = options.remove.split('/');
if (parts.length !== 1) {
throw new Error('Invalid install option. When providing a url, please use the format <plugin>.');
throw new Error('Invalid remove option. Please use the format <plugin>.');
}
settings.package = parts.shift();
} else {
if (parts.length < 2 || parts.length > 3) {
throw new Error('Invalid install option. Please use the format <org>/<plugin>/<version>.');
}
settings.organization = parts.shift();
settings.package = parts.shift();
settings.version = parts.shift();
settings.urls.push(generateDownloadUrl(settings));
settings.urls.push(generateGithubUrl(settings));
}
}
if (options.remove) {
settings.action = 'remove';
parts = options.remove.split('/');
if (parts.length !== 1) {
throw new Error('Invalid remove option. Please use the format <plugin>.');
if (!settings.action || (options.install && options.remove)) {
throw new Error('Please specify either --install or --remove.');
}
settings.package = parts.shift();
if (settings.package) {
settings.pluginPath = path.resolve(__dirname, '..', 'plugins', settings.package);
}
return settings;
}
if (!settings.action || (options.install && options.remove)) {
throw new Error('Please specify either --install or --remove.');
}
if (settings.package) {
settings.pluginPath = path.resolve(__dirname, '..', 'plugins', settings.package);
}
return settings;
}
return {
parse: parse,
parseMilliseconds: parseMilliseconds
};
};

View file

@ -10,47 +10,6 @@ describe('kibana cli', function () {
describe('plugin installer', function () {
describe('settings.action', function () {
function testUsageOfAction(action) {
describe('when action is ' + action, function () {
before(function () {
var program = {
command: function () { return program; },
description: function () { return program; },
option: function () { return program; },
action: function (processCommand) {
processCommand();
}
};
sinon.stub(remover, 'remove');
sinon.stub(installer, 'install');
sinon
.stub(settingParser, 'parse')
.returns({ action: action });
plugin(program);
});
it('calls the right function', function () {
expect(remover.remove.called).to.be(action === 'remove');
expect(installer.install.called).to.be(action === 'install');
});
after(function () {
remover.remove.restore();
installer.install.restore();
settingParser.parse.restore();
});
});
}
testUsageOfAction('remove');
testUsageOfAction('install');
});
describe('commander options', function () {
var program = {

View file

@ -14,7 +14,6 @@ describe('kibana cli', function () {
describe('logger.log', function () {
beforeEach(function () {
logger = pluginLogger(false);
sinon.spy(process.stdout, 'write');
});
@ -23,6 +22,7 @@ describe('kibana cli', function () {
});
it('should log messages to the console and append a new line', function () {
logger = pluginLogger({ silent: false, quiet: false });
var message = 'this is my message';
logger.log(message);
@ -33,6 +33,7 @@ describe('kibana cli', function () {
});
it('should log messages to the console and append not append a new line', function () {
logger = pluginLogger({ silent: false, quiet: false });
for (var i = 0; i < 10; i++) {
logger.log('.', true);
}
@ -54,8 +55,22 @@ describe('kibana cli', function () {
expect(process.stdout.write.getCall(12).args[0]).to.be('\n');
});
it('should not log any messages when quiet is set', function () {
logger = pluginLogger({ silent: false, quiet: true });
var message = 'this is my message';
logger.log(message);
for (var i = 0; i < 10; i++) {
logger.log('.', true);
}
logger.log('Done!');
expect(process.stdout.write.callCount).to.be(0);
});
it('should not log any messages when silent is set', function () {
logger = pluginLogger(true);
logger = pluginLogger({ silent: true, quiet: false });
var message = 'this is my message';
logger.log(message);
@ -73,7 +88,6 @@ describe('kibana cli', function () {
describe('logger.error', function () {
beforeEach(function () {
logger = pluginLogger(false);
sinon.spy(process.stderr, 'write');
});
@ -82,6 +96,15 @@ describe('kibana cli', function () {
});
it('should log error messages to the console and append a new line', function () {
logger = pluginLogger({ silent: false, quiet: false });
var message = 'this is my error';
logger.error(message);
expect(process.stderr.write.calledWith(message + '\n')).to.be(true);
});
it('should log error messages to the console when quiet is set', function () {
logger = pluginLogger({ silent: false, quiet: true });
var message = 'this is my error';
logger.error(message);
@ -89,11 +112,10 @@ describe('kibana cli', function () {
});
it('should not log any error messages when silent is set', function () {
logger = pluginLogger(true);
logger = pluginLogger({ silent: true, quiet: false });
var message = 'this is my error';
logger.error(message);
expect(process.stderr.write.callCount).to.be(0);
});

View file

@ -11,54 +11,56 @@ describe('kibana cli', function () {
describe('parseMilliseconds function', function () {
var parser = settingParser();
it('should return 0 for an empty string', function () {
var value = '';
var result = settingParser.parseMilliseconds(value);
var result = parser.parseMilliseconds(value);
expect(result).to.be(0);
});
it('should return 0 for a number with an invalid unit of measure', function () {
var result = settingParser.parseMilliseconds('1gigablasts');
var result = parser.parseMilliseconds('1gigablasts');
expect(result).to.be(0);
});
it('should assume a number with no unit of measure is specified as milliseconds', function () {
var result = settingParser.parseMilliseconds(1);
var result = parser.parseMilliseconds(1);
expect(result).to.be(1);
result = settingParser.parseMilliseconds('1');
result = parser.parseMilliseconds('1');
expect(result).to.be(1);
});
it('should interpret a number with "s" as the unit of measure as seconds', function () {
var result = settingParser.parseMilliseconds('5s');
var result = parser.parseMilliseconds('5s');
expect(result).to.be(5 * 1000);
});
it('should interpret a number with "second" as the unit of measure as seconds', function () {
var result = settingParser.parseMilliseconds('5second');
var result = parser.parseMilliseconds('5second');
expect(result).to.be(5 * 1000);
});
it('should interpret a number with "seconds" as the unit of measure as seconds', function () {
var result = settingParser.parseMilliseconds('5seconds');
var result = parser.parseMilliseconds('5seconds');
expect(result).to.be(5 * 1000);
});
it('should interpret a number with "m" as the unit of measure as minutes', function () {
var result = settingParser.parseMilliseconds('9m');
var result = parser.parseMilliseconds('9m');
expect(result).to.be(9 * 1000 * 60);
});
it('should interpret a number with "minute" as the unit of measure as minutes', function () {
var result = settingParser.parseMilliseconds('9minute');
var result = parser.parseMilliseconds('9minute');
expect(result).to.be(9 * 1000 * 60);
});
it('should interpret a number with "minutes" as the unit of measure as minutes', function () {
var result = settingParser.parseMilliseconds('9minutes');
var result = parser.parseMilliseconds('9minutes');
expect(result).to.be(9 * 1000 * 60);
});
@ -66,54 +68,79 @@ describe('kibana cli', function () {
describe('parse function', function () {
var options;
var parser;
beforeEach(function () {
options = { install: 'dummy/dummy' };
});
it('should require the user to specify either install and remove', function () {
options.install = null;
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.throwException(/Please specify either --install or --remove./);
expect(parser.parse).withArgs().to.throwError(/Please specify either --install or --remove./);
});
it('should not allow the user to specify both install and remove', function () {
options.remove = 'package';
options.install = 'org/package/version';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.throwException(/Please specify either --install or --remove./);
expect(parser.parse).withArgs().to.throwError(/Please specify either --install or --remove./);
});
var options;
beforeEach(function () {
options = { install: 'dummy/dummy' };
describe('quiet option', function () {
it('should default to false', function () {
parser = settingParser(options);
var settings = parser.parse(options);
expect(settings.quiet).to.be(false);
});
it('should set settings.quiet property to true', function () {
options.parent = { quiet: true };
parser = settingParser(options);
var settings = parser.parse(options);
expect(settings.quiet).to.be(true);
});
});
describe('silent option', function () {
it('should default to false', function () {
var settings = settingParser.parse(options);
parser = settingParser(options);
var settings = parser.parse(options);
expect(settings).to.have.property('silent', false);
});
it('should set settings.silent property to true', function () {
options.silent = true;
var settings = settingParser.parse(options);
parser = settingParser(options);
var settings = parser.parse(options);
expect(settings).to.have.property('silent', true);
});
});
describe('timeout option', function () {
it('should default to 0 (milliseconds)', function () {
var settings = settingParser.parse(options);
parser = settingParser(options);
var settings = parser.parse(options);
expect(settings).to.have.property('timeout', 0);
});
it('should set settings.timeout property to specified value', function () {
options.timeout = 1234;
var settings = settingParser.parse(options);
parser = settingParser(options);
var settings = parser.parse(options);
expect(settings).to.have.property('timeout', 1234);
});
@ -124,19 +151,19 @@ describe('kibana cli', function () {
it('should set settings.action property to "install"', function () {
options.install = 'org/package/version';
var settings = settingParser.parse(options);
parser = settingParser(options);
var settings = parser.parse(options);
expect(settings).to.have.property('action', 'install');
});
it('should allow two parts to the install parameter', function () {
options.install = 'kibana/test-plugin';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.not.throwException();
expect(parser.parse).withArgs().to.not.throwError();
var settings = settingParser.parse(options);
var settings = parser.parse(options);
expect(settings).to.have.property('organization', 'kibana');
expect(settings).to.have.property('package', 'test-plugin');
@ -145,11 +172,11 @@ describe('kibana cli', function () {
it('should allow three parts to the install parameter', function () {
options.install = 'kibana/test-plugin/v1.0.1';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.not.throwException();
expect(parser.parse).withArgs().to.not.throwError();
var settings = settingParser.parse(options);
var settings = parser.parse(options);
expect(settings).to.have.property('organization', 'kibana');
expect(settings).to.have.property('package', 'test-plugin');
@ -158,22 +185,23 @@ describe('kibana cli', function () {
it('should not allow one part to the install parameter', function () {
options.install = 'test-plugin';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.throwException(/Invalid install option. Please use the format <org>\/<plugin>\/<version>./);
expect(parser.parse).withArgs().to.throwError(/Invalid install option. Please use the format <org>\/<plugin>\/<version>./);
});
it('should not allow more than three parts to the install parameter', function () {
options.install = 'kibana/test-plugin/v1.0.1/dummy';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.throwException(/Invalid install option. Please use the format <org>\/<plugin>\/<version>./);
expect(parser.parse).withArgs().to.throwError(/Invalid install option. Please use the format <org>\/<plugin>\/<version>./);
});
it('should populate the urls collection properly when no version specified', function () {
options.install = 'kibana/test-plugin';
parser = settingParser(options);
var settings = settingParser.parse(options);
var settings = parser.parse();
expect(settings.urls).to.have.property('length', 2);
expect(settings.urls).to.contain('https://download.elastic.co/kibana/test-plugin/test-plugin-latest.tar.gz');
@ -182,8 +210,9 @@ describe('kibana cli', function () {
it('should populate the urls collection properly version specified', function () {
options.install = 'kibana/test-plugin/v1.1.1';
parser = settingParser(options);
var settings = settingParser.parse(options);
var settings = parser.parse();
expect(settings.urls).to.have.property('length', 2);
expect(settings.urls).to.contain('https://download.elastic.co/kibana/test-plugin/test-plugin-v1.1.1.tar.gz');
@ -192,8 +221,9 @@ describe('kibana cli', function () {
it('should populate the pluginPath', function () {
options.install = 'kibana/test-plugin';
parser = settingParser(options);
var settings = settingParser.parse(options);
var settings = parser.parse();
var expected = path.resolve(__dirname, '..', '..', '..', '..', '..', 'src', 'server', 'bin', 'plugins', 'test-plugin');
expect(settings).to.have.property('pluginPath', expected);
@ -204,11 +234,11 @@ describe('kibana cli', function () {
it('should allow one part to the install parameter', function () {
options.install = 'test-plugin';
options.url = 'http://www.google.com/plugin.tar.gz';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.not.throwException();
expect(parser.parse).withArgs().to.not.throwError();
var settings = settingParser.parse(options);
var settings = parser.parse();
expect(settings).to.have.property('package', 'test-plugin');
});
@ -216,17 +246,19 @@ describe('kibana cli', function () {
it('should not allow more than one part to the install parameter', function () {
options.url = 'http://www.google.com/plugin.tar.gz';
options.install = 'kibana/test-plugin';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.throwException(/Invalid install option. When providing a url, please use the format <plugin>./);
expect(parser.parse).withArgs()
.to.throwError(/Invalid install option. When providing a url, please use the format <plugin>./);
});
it('should result in only the specified url in urls collection', function () {
var url = 'http://www.google.com/plugin.tar.gz';
options.install = 'test-plugin';
options.url = url;
parser = settingParser(options);
var settings = settingParser.parse(options);
var settings = parser.parse();
expect(settings).to.have.property('urls');
expect(settings.urls).to.be.an('array');
@ -243,8 +275,9 @@ describe('kibana cli', function () {
it('should set settings.action property to "remove"', function () {
options.install = null;
options.remove = 'package';
parser = settingParser(options);
var settings = settingParser.parse(options);
var settings = parser.parse();
expect(settings).to.have.property('action', 'remove');
});
@ -252,8 +285,9 @@ describe('kibana cli', function () {
it('should allow one part to the remove parameter', function () {
options.install = null;
options.remove = 'test-plugin';
parser = settingParser(options);
var settings = settingParser.parse(options);
var settings = parser.parse();
expect(settings).to.have.property('package', 'test-plugin');
});
@ -261,16 +295,18 @@ describe('kibana cli', function () {
it('should not allow more than one part to the install parameter', function () {
options.install = null;
options.remove = 'kibana/test-plugin';
parser = settingParser(options);
expect(settingParser.parse).withArgs(options)
.to.throwException(/Invalid remove option. Please use the format <plugin>./);
expect(parser.parse).withArgs()
.to.throwError(/Invalid remove option. Please use the format <plugin>./);
});
it('should populate the pluginPath', function () {
options.install = null;
options.remove = 'test-plugin';
parser = settingParser(options);
var settings = settingParser.parse(options);
var settings = parser.parse();
var expected = path.resolve(__dirname, '..', '..', '..', '..', '..', 'src', 'server', 'bin', 'plugins', 'test-plugin');
expect(settings).to.have.property('pluginPath', expected);