Initial commit.
This commit is contained in:
commit
b526067eeb
15
packages/xo-cli/.editorconfig
Normal file
15
packages/xo-cli/.editorconfig
Normal file
@ -0,0 +1,15 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
#
|
||||
# Tab indentation (size of 2 spaces)
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespaces = true
|
1
packages/xo-cli/.gitignore
vendored
Normal file
1
packages/xo-cli/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/node_modules/
|
126
packages/xo-cli/.jshintrc
Normal file
126
packages/xo-cli/.jshintrc
Normal file
@ -0,0 +1,126 @@
|
||||
{
|
||||
// --------------------------------------------------------------------
|
||||
// JSHint Configuration, Node.js Edition
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// This is an options template for [JSHint][1], forked from
|
||||
// haschek's [JSHint template][2]:
|
||||
//
|
||||
// * the environment has been changed to `node`;
|
||||
// * recent options were added;
|
||||
// * coding style has been adapted to node (e.g. 2 spaces
|
||||
// indenting, global use strict).
|
||||
//
|
||||
// [1]: http://www.jshint.com/
|
||||
// [2]: https://gist.github.com/haschek/2595796
|
||||
//
|
||||
// @author Julien Fontanet <julien.fontanet@isonoe.net>
|
||||
// @license http://unlicense.org/
|
||||
|
||||
// == Enforcing Options ===============================================
|
||||
//
|
||||
// These options tell JSHint to be more strict towards your code. Use
|
||||
// them if you want to allow only a safe subset of JavaScript, very
|
||||
// useful when your codebase is shared with a big number of developers
|
||||
// with different skill levels.
|
||||
|
||||
"bitwise" : true, // Prohibit bitwise operators (&, |, ^, etc.).
|
||||
"camelcase" : true, // Require variable names to use either camelCase or UPPER_CASE styles.
|
||||
"curly" : true, // Require {} for every new block or scope.
|
||||
"eqeqeq" : true, // Require triple equals i.e. `===`.
|
||||
"forin" : true, // Tolerate `for in` loops without `hasOwnPrototype`.
|
||||
"freeze" : true, // Prohibit modification of native objects' prototypes.
|
||||
"immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
|
||||
"indent" : 2, // Specify indentation spacing
|
||||
"latedef" : true, // Prohibit variable use before definition.
|
||||
"newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
|
||||
"noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
|
||||
"noempty" : true, // Prohibit use of empty blocks.
|
||||
"nonew" : true, // Prohibit use of constructors for side-effects.
|
||||
"plusplus" : false, // Prohibit the use of `++` & `--`.
|
||||
"quotmark" : "'", // Require single quotes.
|
||||
"undef" : true, // Require all non-global variables be declared before they are used.
|
||||
"unused" : true, // Prohibit unused variables.
|
||||
"strict" : true, // Require `use strict` pragma in every function.
|
||||
"trailing" : true, // Prohibit trailing whitespaces.
|
||||
"maxparams" : 4, // Prohibit more than 4 parameters per function definition.
|
||||
"maxdepth" : 3, // Prohibit nesting more than 3 control blocks.
|
||||
"maxstatements" : 20, // Prohibit more than 20 statements per function.
|
||||
"maxcomplexity" : 7, // Prohibit having to much branches in your code.
|
||||
"maxlen" : 80, // Prohibit line with more than 80 characters.
|
||||
|
||||
// == Relaxing Options ================================================
|
||||
//
|
||||
// These options allow you to suppress certain types of warnings. Use
|
||||
// them only if you are absolutely positive that you know what you are
|
||||
// doing.
|
||||
|
||||
"asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons).
|
||||
"boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
|
||||
"debug" : false, // Allow debugger statements e.g. browser breakpoints.
|
||||
"eqnull" : false, // Tolerate use of `== null`.
|
||||
"es5" : false, // Allow EcmaScript 5 syntax.
|
||||
"esnext" : false, // Allow ES.next specific features such as `const` and `let`.
|
||||
"evil" : false, // Tolerate use of `eval`.
|
||||
"expr" : true, // Tolerate `ExpressionStatement` as Programs. (Allowed for Mocha.)
|
||||
"funcscope" : false, // Tolerate declarations of variables inside of control structures while accessing them later from the outside.
|
||||
"gcl" : false, // Makes JSHint compatible with Google Closure Compiler.
|
||||
"globalstrict" : true, // Allow global "use strict" (also enables 'strict').
|
||||
"iterator" : false, // Allow usage of __iterator__ property.
|
||||
"lastsemic" : false, // Tolerat missing semicolons when the it is omitted for the last statement in a one-line block.
|
||||
"laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
|
||||
"laxcomma" : false, // Suppress warnings about comma-first coding style.
|
||||
"loopfunc" : false, // Allow functions to be defined within loops.
|
||||
"maxerr" : 50, // Maximum errors before stopping.
|
||||
"moz" : false, // Tolerate Mozilla JavaScript extensions.
|
||||
"notypeof" : false, // Tolerate invalid typeof values.
|
||||
"multistr" : false, // Tolerate multi-line strings.
|
||||
"proto" : false, // Tolerate __proto__ property. This property is deprecated.
|
||||
"scripturl" : false, // Tolerate script-targeted URLs.
|
||||
"smarttabs" : false, // Tolerate mixed tabs and spaces when the latter are used for alignmnent only.
|
||||
"shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
|
||||
"sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
|
||||
"supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
|
||||
"validthis" : false, // Tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function.
|
||||
|
||||
// == Environments ====================================================
|
||||
//
|
||||
// These options pre-define global variables that are exposed by
|
||||
// popular JavaScript libraries and runtime environments—such as
|
||||
// browser or node.js.
|
||||
|
||||
"browser" : true, // Standard browser globals e.g. `window`, `document`.
|
||||
"couch" : false, // Enable globals exposed by CouchDB.
|
||||
"devel" : false, // Allow development statements e.g. `console.log();`.
|
||||
"dojo" : false, // Enable globals exposed by Dojo Toolkit.
|
||||
"jquery" : false, // Enable globals exposed by jQuery JavaScript library.
|
||||
"mootools" : false, // Enable globals exposed by MooTools JavaScript framework.
|
||||
"node" : true, // Enable globals available when code is running inside of the NodeJS runtime environment.
|
||||
"nonstandard" : false, // Define non-standard but widely adopted globals such as escape and unescape.
|
||||
"phantom" : false, // Enable globals exposed by PhantomJS.
|
||||
"prototypejs" : false, // Enable globals exposed by Prototype JavaScript framework.
|
||||
"rhino" : false, // Enable globals available when your code is running inside of the Rhino runtime environment.
|
||||
"worker" : false, // Enable globals exposed when running inside a Web Worker.
|
||||
"wsh" : false, // Enable globals available when your code is running as a script for the Windows Script Host.
|
||||
"yui" : false, // Enable globals exposed by YUI.
|
||||
|
||||
// == JSLint Legacy ===================================================
|
||||
//
|
||||
// These options are legacy from JSLint. Aside from bug fixes they will
|
||||
// not be improved in any way and might be removed at any point.
|
||||
|
||||
"nomen" : false, // Prohibit use of initial or trailing underbars in names.
|
||||
"onevar" : false, // Allow only one `var` statement per function.
|
||||
"passfail" : false, // Stop on first error.
|
||||
"white" : false, // Check against strict whitespace and indentation rules.
|
||||
|
||||
"globals": {
|
||||
// Mocha.
|
||||
"after" : false,
|
||||
"afterEach" : false,
|
||||
"before" : false,
|
||||
"beforeEach" : false,
|
||||
"describe" : false,
|
||||
"it" : false
|
||||
}
|
||||
}
|
20
packages/xo-cli/README.md
Normal file
20
packages/xo-cli/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# XO CLI
|
||||
[](http://travis-ci.org/vatesfr/xo-cli)
|
||||
[](https://david-dm.org/vatesfr/xo-cli)
|
||||
[](https://david-dm.org/vatesfr/xo-cli#info=devDependencies)
|
||||
|
||||
> Basic CLI for Xen-Orchestra
|
||||
|
||||
## Installation
|
||||
|
||||
#### [npm](https://npmjs.org/package/xo-cli)
|
||||
|
||||
```
|
||||
npm install -f xo-cli
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
xo-cli add-server
|
||||
```
|
7
packages/xo-cli/bin/xo-cli
Executable file
7
packages/xo-cli/bin/xo-cli
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
//====================================================================
|
||||
|
||||
require('../')(process.argv.slice(2));
|
187
packages/xo-cli/cli.js
Normal file
187
packages/xo-cli/cli.js
Normal file
@ -0,0 +1,187 @@
|
||||
'use strict';
|
||||
|
||||
//====================================================================
|
||||
|
||||
var _ = require('lodash');
|
||||
var nomnom = require('nomnom');
|
||||
var Promise = require('bluebird');
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
var prompt = require('./prompt');
|
||||
var Xo = require('./xo');
|
||||
|
||||
//====================================================================
|
||||
|
||||
// Handles a promise in a CLI environment.
|
||||
var handlePromise = function (promise) {
|
||||
promise.then(function (value) {
|
||||
if (_.isString(value))
|
||||
{
|
||||
console.log(value);
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
}).catch(function (error) {
|
||||
if (_.isString(error))
|
||||
{
|
||||
console.error(error);
|
||||
}
|
||||
else if (_.isNumber(error))
|
||||
{
|
||||
process.exit(error);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
var connect = function (opts) {
|
||||
var config, xo;
|
||||
|
||||
return Promise.try(function () {
|
||||
opts || (opts = {});
|
||||
|
||||
// TODO: reads the configuration file.
|
||||
config = {
|
||||
server: 'ws://localhost:9000/api/',
|
||||
};
|
||||
|
||||
if (!config.server)
|
||||
{
|
||||
throw 'no server to connect to!';
|
||||
}
|
||||
|
||||
xo = new Xo(config.server);
|
||||
|
||||
if (config.token && !opts.noAutoSignIn)
|
||||
{
|
||||
return xo.send('session.signInWithToken', {
|
||||
token: config.token,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
var addServer = function (host, username, password) {
|
||||
return connect().then(function (connection) {
|
||||
return connection.send('server.add', {
|
||||
host: host,
|
||||
username: username,
|
||||
password: password,
|
||||
});
|
||||
}).return('ok');
|
||||
};
|
||||
|
||||
var register = function (url, email, password) {
|
||||
var xo;
|
||||
return Promise.try(function () {
|
||||
xo = new Xo(url);
|
||||
|
||||
return xo.send('session.signInWithPassword', {
|
||||
email: email,
|
||||
password: password,
|
||||
});
|
||||
}).then(function (user) {
|
||||
console.log('Successfully logged with', user.email);
|
||||
|
||||
return xo.send('token.create');
|
||||
}).then(function (token) {
|
||||
return getConfig().set({
|
||||
server: url,
|
||||
token: token,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//====================================================================
|
||||
|
||||
module.exports = function (argv) {
|
||||
nomnom.command('register')
|
||||
.help('signs in XO using email/password')
|
||||
.options({
|
||||
url: {
|
||||
help: 'URL of the API endpoint',
|
||||
},
|
||||
email: {
|
||||
help: 'email to use to connect',
|
||||
},
|
||||
password: {
|
||||
help: 'password to use to connect',
|
||||
},
|
||||
})
|
||||
.callback(function (opts) {
|
||||
Promise.try(function () {
|
||||
if (opts.url)
|
||||
{
|
||||
return prompt.input('URL').then(function (url) {
|
||||
opts.url = url;
|
||||
});
|
||||
}
|
||||
}).then(function () {
|
||||
if (!opts.email)
|
||||
{
|
||||
return prompt.input('Email').then(function (email) {
|
||||
opts.email = email;
|
||||
});
|
||||
}
|
||||
}).then(function () {
|
||||
if (!opts.password)
|
||||
{
|
||||
return prompt.password('Password').then(function (password) {
|
||||
opts.password = password;
|
||||
});
|
||||
}
|
||||
}).then(function () {
|
||||
return register(opts.url, opts.email, opts.password);
|
||||
});
|
||||
})
|
||||
;
|
||||
|
||||
nomnom.command('add-server')
|
||||
.help('adds a new server')
|
||||
.options({
|
||||
host: {
|
||||
help: 'hostname or ip of the server',
|
||||
},
|
||||
username: {
|
||||
help: 'username to use to connect',
|
||||
},
|
||||
password: {
|
||||
help: 'password to use to connect',
|
||||
},
|
||||
})
|
||||
.callback(function (opts) {
|
||||
Promise.try(function () {
|
||||
if (opts.host)
|
||||
{
|
||||
return prompt.input('Hostname or ip').then(function (host) {
|
||||
opts.host = host;
|
||||
});
|
||||
}
|
||||
}).then(function () {
|
||||
if (!opts.username)
|
||||
{
|
||||
return prompt.input('Username').then(function (username) {
|
||||
opts.username = username;
|
||||
});
|
||||
}
|
||||
}).then(function () {
|
||||
if (!opts.password)
|
||||
{
|
||||
return prompt.password('Password').then(function (password) {
|
||||
opts.password = password;
|
||||
});
|
||||
}
|
||||
}).then(function () {
|
||||
return addServer(opts.host, opts.username, opts.password);
|
||||
});
|
||||
})
|
||||
;
|
||||
|
||||
nomnom.parse(argv);
|
||||
};
|
11
packages/xo-cli/config.js
Normal file
11
packages/xo-cli/config.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
//====================================================================
|
||||
|
||||
var xdg = require('xdg').basedir;
|
||||
|
||||
//====================================================================
|
||||
|
||||
var Config = function () {
|
||||
this.data =
|
||||
};
|
34
packages/xo-cli/package.json
Normal file
34
packages/xo-cli/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "xo-cli",
|
||||
"version": "0.1.0",
|
||||
"description": "Basic CLI for Xen-Orchestra",
|
||||
"author": "Julien Fontanet <julien.fontanet@vates.fr>",
|
||||
"homepage": "https://github.com/vatesfr/xo-cli",
|
||||
"bugs": "https://github.com/vatesfr/xo-cli",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vatesfr/xo-cli"
|
||||
},
|
||||
"dependencies": {
|
||||
"bluebird": "^1.1.0",
|
||||
"chalk": "^0.4.0",
|
||||
"inquirer": "^0.4.1",
|
||||
"lodash": "^2.4.1",
|
||||
"nomnom": "^1.6.2",
|
||||
"ws": "^0.4.31",
|
||||
"xdg": "^0.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^1.9.0",
|
||||
"mocha": "^1.18.0",
|
||||
"mocha-promise": "0.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha cli.spec.js"
|
||||
},
|
||||
"main": "cli.js",
|
||||
"bin": {
|
||||
"xo-cli": "bin/xo-cli"
|
||||
},
|
||||
"license": "AGPL3"
|
||||
}
|
32
packages/xo-cli/prompt.js
Normal file
32
packages/xo-cli/prompt.js
Normal file
@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
//====================================================================
|
||||
|
||||
var inquirer = require('inquirer');
|
||||
var Promise = require('bluebird');
|
||||
|
||||
//====================================================================
|
||||
|
||||
var prompts = module.exports = function (prompts) {
|
||||
var deferred = Promise.defer();
|
||||
|
||||
inquirer.prompt(prompts, deferred.resolve.bind(deferred));
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
exports.input = function (message) {
|
||||
return prompts({
|
||||
type: 'input',
|
||||
name: 'question',
|
||||
message: message,
|
||||
}).get('question');
|
||||
};
|
||||
|
||||
exports.password = function (message) {
|
||||
return prompts({
|
||||
type: 'password',
|
||||
name: 'question',
|
||||
message: message,
|
||||
}).get('question');
|
||||
};
|
123
packages/xo-cli/xo.js
Normal file
123
packages/xo-cli/xo.js
Normal file
@ -0,0 +1,123 @@
|
||||
'use strict';
|
||||
|
||||
//====================================================================
|
||||
|
||||
var _ = require('lodash');
|
||||
|
||||
var Promise = require('bluebird');
|
||||
|
||||
// Supports browsers.
|
||||
// FIXME: wraps in an anonymous function.
|
||||
var WebSocket = 'WebSocket' in window ? window.WebSocket : require('ws');
|
||||
|
||||
//====================================================================
|
||||
|
||||
var Xo = function (url) {
|
||||
this._url = url;
|
||||
|
||||
// Identifier of the next request.
|
||||
this._nextId = 0;
|
||||
|
||||
// Promises linked to the requests.
|
||||
this._deferreds = {};
|
||||
|
||||
// Current WebSocket.
|
||||
this._socket = null;
|
||||
|
||||
// Current status which may be:
|
||||
// - disconnected
|
||||
// - connecting
|
||||
// - connected
|
||||
this.status = 'disconnected';
|
||||
};
|
||||
|
||||
_.extend(Xo.prototype, {
|
||||
connect: function () {
|
||||
if (this.status === 'connected')
|
||||
{
|
||||
return Promise.cast();
|
||||
}
|
||||
|
||||
var deferred = Promise.defer();
|
||||
|
||||
this.status = 'connecting';
|
||||
|
||||
var socket = this._socket = new WebSocket(this._url);
|
||||
|
||||
// When the socket opens, send any queued requests.
|
||||
socket.on('open', function () {
|
||||
this.status = 'connected';
|
||||
|
||||
// Reopens accesses.
|
||||
delete this.send;
|
||||
}.bind(this));
|
||||
|
||||
socket.on('message', function (event) {
|
||||
// TODO: Wraps in a promise to prevent releasing the Zalgo.
|
||||
var response = JSON.parse(event.data);
|
||||
|
||||
var id = response.id;
|
||||
|
||||
var deferred = this._deferreds[id];
|
||||
if (!deferred)
|
||||
{
|
||||
// Response already handled.
|
||||
return;
|
||||
}
|
||||
delete this._deferreds[id];
|
||||
|
||||
if ('error' in response)
|
||||
{
|
||||
return deferred.reject(response.error);
|
||||
}
|
||||
|
||||
if ('result' in response)
|
||||
{
|
||||
return deferred.resolve(response.result);
|
||||
}
|
||||
|
||||
deferred.reject({
|
||||
message: 'invalid response received',
|
||||
object: response,
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('close', function () {
|
||||
// Closes accesses.
|
||||
this.send = function () {
|
||||
throw new Error('not connected');
|
||||
};
|
||||
|
||||
// Fails all waiting requests.
|
||||
_.each(this._deferreds, function (deferred) {
|
||||
deferred.reject('not connected');
|
||||
});
|
||||
this._deferreds = {};
|
||||
}.bind(this));
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
send: function (method, params) {
|
||||
return this.connect().then(function () {
|
||||
var socket = this._socket;
|
||||
|
||||
var id = this._nextId++;
|
||||
|
||||
socket.send(JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: id,
|
||||
method: method,
|
||||
params: params || [],
|
||||
}));
|
||||
|
||||
var deferred = this._deferreds[id] = Promise.defer();
|
||||
|
||||
return deferred.promise;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
//====================================================================
|
||||
|
||||
module.exports = Xo;
|
Loading…
Reference in New Issue
Block a user