pm2/test/interface/scoped_pm2_actions.mocha.js

259 lines
6.8 KiB
JavaScript

var PM2 = require('../..');
var should = require('should');
var nssocket = require('nssocket');
var events = require('events');
var util = require('util');
var Cipher = require('../../lib/Interactor/Cipher.js');
var cst = require('../../constants.js');
var Plan = require('../helpers/plan.js');
var Configuration = require('../../lib/Configuration.js');
var Helpers = require('../helpers/apps.js');
var Interactor = require('../../lib/Interactor/InteractorDaemonizer.js');
var gl_interactor_process;
var send_cmd = new events.EventEmitter();
process.env.NODE_ENV = 'local_test';
var meta_connect = {
secret_key : 'test-secret-key',
public_key : 'test-public-key',
machine_name : 'test-machine-name'
};
/**
* Description
* @method forkInteractor
* @return CallExpression
*/
function forkInteractor(cb) {
Interactor.launchAndInteract(meta_connect, function(err, data, interactor_process) {
gl_interactor_process = interactor_process;
cb();
});
}
/**
* Mock server receiving data
* @method forkInteractor
* @return CallExpression
*/
function createMockServer(cb) {
var server = nssocket.createServer(function(_socket) {
send_cmd.on('cmd', function(data) {
if (process.env.DEBUG)
console.log('Sending command %j', data);
_socket.send(data._type, data);
});
_socket.data('*', function(data) {
this.event.forEach(function(ev) {
send_cmd.emit(ev, data);
});
});
});
server.on('error', function(e) {
throw new Error(e);
});
server.on('listening', function() {
cb(null, server);
});
server.listen(4322, '0.0.0.0');
}
function startSomeApps(cb) {
pm2.start('./child.js', {instances : 1, name : 'child'}, cb);
}
var pm2 = new PM2.custom({
independent : true,
cwd : __dirname + '/../fixtures',
secret_key : 'test-secret-key',
public_key : 'test-public-key',
machine_name : 'test-machine-name',
daemon_mode: true
});
describe('SCOPED PM2 ACTIONS', function() {
var server;
var interactor;
this.timeout(5000);
after(function(done) {
server.close();
pm2.destroy(done);
});
before(function(done) {
createMockServer(function(err, _server) {
server = _server;
pm2.connect(function() {
startSomeApps(function(err) {
gl_interactor_process = pm2.Client.interactor_process;
// @todo: would be nice to know when an app is ready
// @priotity: minor
setTimeout(done, 1500);
});
});
});
});
it('should send ask, receive ask:rep and identify agent', function(done) {
send_cmd.once('ask:rep', function(pck) {
var data = Cipher.decipherMessage(pck.data, meta_connect.secret_key);
data.machine_name.should.eql(meta_connect.machine_name);
done();
});
send_cmd.emit('cmd', { _type : 'ask' });
});
/**
* PM2 agent is now identified
*/
describe('Test non auth remote commands', function() {
before(function(done) {
Configuration.unset('pm2:passwd', function(err, data) {
should.not.exists(err);
done();
});
});
it('should restart command via scoped pm2 action (no pass needed)', function(done) {
var good = false;
var plan = new Plan(2, function() {
gl_interactor_process.removeListener('message', actionCheck);
good = true;
done();
});
function actionCheck(pck) {
if (good) return false;
if (pck.event == 'pm2:scoped:stream' && pck.data.out === 'Action restart received')
return plan.ok(true);
if (pck.event == 'pm2:scoped:end')
return plan.ok(true);
if (pck.event == 'pm2:scoped:error')
return plan.ok(false, pck);
return false;
}
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'restart',
uuid : '1234',
options : { args : ['child'] }
});
});
});
describe('Password verification', function() {
before(function(done) {
Configuration.unset('pm2:passwd', function(err, data) {
should.not.exists(err);
done();
});
});
it('should error when call an action that is password protected', function(done) {
function actionCheck(pck) {
if (pck.event == 'pm2:scoped:error' && pck.data.out.indexOf('Missing password') > -1) {
gl_interactor_process.removeListener('message', actionCheck);
done();
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'install',
uuid : '5678',
options : { args : ['child'] }
});
});
it('should fail when password passed but no pm2 password configured', function(done) {
function actionCheck(pck) {
if (pck.event == 'pm2:scoped:error' && pck.data.out.indexOf('Password at PM2') > -1) {
gl_interactor_process.removeListener('message', actionCheck);
done();
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'install',
uuid : '5678',
password : 'random-pass',
options : { args : ['pm2-module'] }
});
});
it('should set a password', function(done) {
pm2.set('pm2:passwd', 'testpass', function(err, data) {
should.not.exists(err);
done();
});
});
it('should fail when wrong password', function(done) {
function actionCheck(pck) {
if (pck.event == 'pm2:scoped:error' && pck.data.out.indexOf('Password does not match') > -1) {
gl_interactor_process.removeListener('message', actionCheck);
setTimeout(done, 100);
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'install',
uuid : '5678',
password : 'random-pass',
options : { args : ['pm2-module'] }
});
});
it('should work when good password passed', function(done) {
function actionCheck(pck) {
if (pck.event === 'pm2:scoped:end') {
gl_interactor_process.removeListener('message', actionCheck);
done();
}
if (pck.event === 'pm2:scoped:error') {
gl_interactor_process.removeListener('message', actionCheck);
done('{ERROR} Wrong password!' + JSON.stringify(pck));
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'ping',
uuid : '5678',
password : 'testpass',
options : {}
});
});
});
});