module system v3: independant folder for each module + retrocompat v2/v3

This commit is contained in:
Unitech 2017-12-03 16:17:22 +01:00
parent 58369a5533
commit b5372aa19e
8 changed files with 530 additions and 262 deletions

View File

@ -440,8 +440,11 @@ commander.command('update')
*/
commander.command('install <module|git:// url>')
.alias('module:install')
.option('--v1', 'install module in v1 manner (do not use it)')
.description('install or update a module and run it forever')
.action(function(plugin_name) {
.action(function(plugin_name, opts) {
if (opts.v1)
commander.v1 = true;
pm2.install(plugin_name, commander);
});

View File

@ -14,19 +14,13 @@ var chalk = require('chalk');
var Configuration = require('../../Configuration.js');
var cst = require('../../../constants.js');
var Common = require('../../Common');
var UX = require('../CliUx.js');
var Utility = require('../../Utility.js');
var semver = require('semver');
var ModularizerV1 = require('./Modularizerv1.js');
var Modularizer = module.exports = {};
var MODULE_CONF_PREFIX = 'module-db';
var MODULE_CONF_PREFIX = 'module-db-v2';
function startModule(CLI, opts, cb) {
/** SCRIPT
* Open file and make the script detection smart
*/
if (!opts.cmd) throw new Error('module package.json not defined');
if (!opts.development_mode) opts.development_mode = false;
@ -51,16 +45,6 @@ function startModule(CLI, opts, cb) {
}
}
/**
* Verify that the module is valid
* If not, delete
*/
if (isValidModule(package_json) === false) {
if (!opts.development_mode) shelljs.rm('-rf', opts.proc_pabth);
Common.printError(cst.PREFIX_MSG_MOD + 'Module uninstalled');
return cb(new Error('Invalid module (script is missing)'));
}
Common.extend(opts, {
cwd : opts.proc_path,
watch : opts.development_mode,
@ -75,7 +59,7 @@ function startModule(CLI, opts, cb) {
});
};
function installModule(CLI, module_name, opts, cb) {
Modularizer.installModule = function(CLI, module_name, opts, cb) {
var proc_path = '',
cmd = '',
conf = {},
@ -87,9 +71,9 @@ function installModule(CLI, module_name, opts, cb) {
}
if (module_name == '.') {
/**
/*******************
* Development mode
*/
*******************/
Common.printOut(cst.PREFIX_MSG_MOD + 'Installing local module in DEVELOPMENT MODE with WATCH auto restart');
development_mode = true;
proc_path = process.cwd();
@ -107,100 +91,94 @@ function installModule(CLI, module_name, opts, cb) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
return cb(null, dt);
});
return false;
}
else {
/**
* Production mode
*/
var cli = {};
if (semver.satisfies(process.version, '> 0.12') && shelljs.which('yarn')) {
cli = {
bin : 'yarn',
cmd : 'add'
}
}
else {
cli = {
bin : 'npm',
cmd : 'install'
}
/******************
* Production mode
******************/
Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[NPM]') + ' to install ' + module_name + ' ...');
var canonic_module_name = Utility.getCanonicModuleName(module_name);
var install_path = path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name);
var install_instance = spawn(cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error', '--prefix', install_path ], {
stdio : 'inherit',
env: process.env,
shell : true
});
install_instance.on('close', finalize);
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
function finalize(code) {
if (code != 0) {
// @todo Rollback
return cb(new Error("Installation failed"));
}
Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[' + cli.bin.toUpperCase() + ']') + ' to install ' + module_name + ' ...');
Common.printOut(cst.PREFIX_MSG_MOD + 'Module downloaded');
var install_instance = spawn(cst.IS_WINDOWS ? cli.bin + '.cmd' : cli.bin, [cli.cmd, module_name, '--loglevel=error'], {
stdio : 'inherit',
env: process.env,
shell : true,
cwd : cst.PM2_ROOT_PATH
var proc_path = path.join(install_path, 'node_modules', canonic_module_name);
var package_json_path = path.join(proc_path, 'package.json');
// Append default configuration to module configuration
try {
var conf = JSON.parse(fs.readFileSync(package_json_path).toString()).config;
if (conf) {
Object.keys(conf).forEach(function(key) {
Configuration.setSyncIfNotExist(canonic_module_name + ':' + key, conf[key]);
});
}
} catch(e) {
Common.printError(e);
}
opts = Common.extend(opts, {
cmd : package_json_path,
development_mode : development_mode,
proc_path : proc_path
});
install_instance.on('close', finalize);
Configuration.set(MODULE_CONF_PREFIX + ':' + canonic_module_name, {
uid : opts.uid,
gid : opts.gid
}, function(err, data) {
if (err) return cb(err);
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
startModule(CLI, opts, function(err, dt) {
if (err) return cb(err);
function finalize(code) {
if (code != 0) {
return cb(new Error("Installation failed"));
}
if (process.env.PM2_PROGRAMMATIC === 'true')
return cb(null, dt);
Common.printOut(cst.PREFIX_MSG_MOD + 'Module downloaded');
var canonic_module_name = Utility.getCanonicModuleName(module_name);
proc_path = p.join(cst.PM2_ROOT_PATH, 'node_modules', canonic_module_name);
cmd = p.join(proc_path, cst.DEFAULT_MODULE_JSON);
/**
* Append default configuration to module configuration
*/
try {
var conf = JSON.parse(fs.readFileSync(path.join(proc_path, 'package.json')).toString()).config;
if (conf) {
Object.keys(conf).forEach(function(key) {
Configuration.setSyncIfNotExist(canonic_module_name + ':' + key, conf[key]);
});
}
} catch(e) {
Common.printError(e);
}
opts = Common.extend(opts, {
cmd : cmd,
development_mode : development_mode,
proc_path : proc_path
});
Configuration.set(MODULE_CONF_PREFIX + ':' + canonic_module_name, {
uid : opts.uid,
gid : opts.gid
}, function(err, data) {
startModule(CLI, opts, function(err, dt) {
if (err) return cb(err);
if (process.env.PM2_PROGRAMMATIC === 'true')
return cb(null, dt);
CLI.conf(canonic_module_name, function() {
Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
Common.printOut(cst.PREFIX_MSG_MOD + 'Edit configuration via: `pm2 conf`');
return cb(null, dt);
});
CLI.conf(canonic_module_name, function() {
Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
Common.printOut(cst.PREFIX_MSG_MOD + 'Edit configuration via: `pm2 conf`');
return cb(null, dt);
});
});
}
});
}
}
function uninstallModule(CLI, module_name, cb) {
var proc_path = p.join(cst.PM2_ROOT_PATH, 'node_modules', module_name);
Configuration.unsetSync(MODULE_CONF_PREFIX + ':' + module_name);
try {
// v1 uninstallation
fs.statSync(proc_path)
Configuration.unsetSync('module-db:' + module_name);
} catch(e) {
proc_path = p.join(cst.DEFAULT_MODULE_PATH, module_name, 'node_modules', module_name);
Configuration.unsetSync(MODULE_CONF_PREFIX + ':' + module_name);
}
CLI.deleteModule(module_name, function(err, data) {
if (err) {
@ -222,117 +200,6 @@ function uninstallModule(CLI, module_name, cb) {
});
}
function installLangModule(module_name, cb) {
var node_module_path = path.resolve(path.join(__dirname, '../../../'));
var cli = semver.satisfies(process.version, '> 0.12') && shelljs.which('yarn') ? 'yarn' : 'npm'
Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[' + cli.toUpperCase() + ']') + ' to install ' + module_name + ' ...');
var install_instance = spawn(cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error'], {
stdio : 'inherit',
env: process.env,
shell : true,
cwd : node_module_path
});
install_instance.on('close', function(code) {
if (code > 0)
return cb(new Error('Module install failed'));
return cb(null);
});
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
};
/**
* List modules on the old way
*/
var listModules = function() {
var module_folder = p.join(cst.PM2_ROOT_PATH, 'node_modules');
var ret = {};
shelljs.config.silent = true;
var modules = shelljs.ls(module_folder);
shelljs.config.silent = false;
modules.forEach(function(module_name) {
if (module_name.indexOf('pm2-') > -1)
ret[module_name] = {};
});
return ret;
};
/**
* List modules based on internal database
*/
var listModulesV2 = Modularizer.listModules = function() {
var config = Configuration.getSync(MODULE_CONF_PREFIX);
if (!config) {
var modules_already_installed = listModules();
Object.keys(modules_already_installed).forEach(function(module_name) {
Configuration.setSync(MODULE_CONF_PREFIX + ':' + module_name, {});
});
return modules_already_installed;
}
return config;
};
Modularizer.getAdditionalConf = function(app_name) {
if (!app_name) throw new Error('No app_name defined');
var module_conf = Configuration.getAllSync();
var additional_env = {};
if (!module_conf[app_name]) {
additional_env = {};
additional_env[app_name] = {};
}
else {
additional_env = Common.clone(module_conf[app_name]);
additional_env[app_name] = JSON.stringify(module_conf[app_name]);
}
return additional_env;
};
Modularizer.launchAll = function(CLI, cb) {
var module_folder = p.join(cst.PM2_ROOT_PATH, 'node_modules');
var modules = listModulesV2();
async.eachLimit(Object.keys(modules), 1, function(module, next) {
var pmod = p.join(module_folder, module, cst.DEFAULT_MODULE_JSON);
Common.printOut(cst.PREFIX_MSG_MOD + 'Starting module ' + module);
var opts = {};
if (modules[module] != true) {
Common.extend(opts, modules[module]);
}
Common.extend(opts, {
cmd : pmod,
development_mode : false,
proc_path : p.join(module_folder, module)
});
startModule(CLI, opts, function(err, dt) {
if (err) console.error(err);
return next();
});
}, function() {
return cb ? cb(null) : false;
});
};
Modularizer.install = function(CLI, module_name, opts, cb) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Installing module ' + module_name);
@ -341,7 +208,7 @@ Modularizer.install = function(CLI, module_name, opts, cb) {
if (module_name == 'v8-profiler' || module_name == 'profiler') {
installLangModule('v8-profiler-node8', function(err) {
if (err) {
Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green('Profling installation has FAILED (checkout previous logs)'));
Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green('Profiling installation has FAILED (checkout previous logs)'));
return cb(err);
}
@ -386,25 +253,73 @@ Modularizer.install = function(CLI, module_name, opts, cb) {
return false;
}
// Update
moduleExist(CLI, canonic_module_name, function(exists) {
if (moduleExist(canonic_module_name) === true) {
/**
* Update
*/
Common.printOut(cst.PREFIX_MSG_MOD + 'Module already installed. Updating.');
if (exists) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Module already installed. Updating.');
uninstallModule(CLI, canonic_module_name, function(err) {
return installModule(CLI, module_name, opts, cb);
return uninstallModule(CLI, canonic_module_name, function(err) {
return ModularizerV1.installModule(CLI, module_name, opts, cb);
});
}
// Install
Modularizer.installModule(CLI, module_name, opts, cb);
})
};
// Start V1 and V2 modules
Modularizer.launchAll = function(CLI, cb) {
ModularizerV1.launchModules(CLI, function() {
Modularizer.launchModules(CLI, cb);
});
};
/**
* List modules based on modules present in ~/.pm2/modules/ folder
*/
Modularizer.listModules = function() {
return Configuration.getSync(MODULE_CONF_PREFIX);
};
Modularizer.launchModules = function(CLI, cb) {
var modules = Modularizer.listModules();
if (!modules) return cb();
async.eachLimit(Object.keys(modules), 1, function(module_name, next) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Starting module ' + module_name);
var install_path = path.join(cst.DEFAULT_MODULE_PATH, module_name);
var proc_path = path.join(install_path, 'node_modules', module_name);
var package_json_path = path.join(proc_path, 'package.json');
var opts = {};
// Merge with embedded configuration inside module_conf (uid, gid)
Common.extend(opts, modules[module_name]);
// Merge meta data to start module properly
Common.extend(opts, {
// package.json path
cmd : package_json_path,
// starting mode
development_mode : false,
// process cwd
proc_path : proc_path
});
return false;
}
startModule(CLI, opts, function(err, dt) {
if (err) console.error(err);
return next();
});
/**
* Install
*/
installModule(CLI, module_name, opts, cb);
};
}, function() {
return cb ? cb(null) : false;
});
}
/**
* Uninstall module
@ -412,12 +327,11 @@ Modularizer.install = function(CLI, module_name, opts, cb) {
Modularizer.uninstall = function(CLI, module_name, cb) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Uninstalling module ' + module_name);
//if (moduleExist(module_name) === false && module_name != '.') {
//Common.printError(cst.PREFIX_MSG_MOD_ERR + 'Module unknown.');
//return cb({msg:'Module unknown'});
//}
if (module_name == 'all') {
var modules = listModulesV2();
var modules = Modularizer.listModules();
if (!modules) return cb();
async.forEachLimit(Object.keys(modules), 1, function(module, next) {
uninstallModule(CLI, module, next);
}, cb);
@ -428,6 +342,28 @@ Modularizer.uninstall = function(CLI, module_name, cb) {
uninstallModule(CLI, canonic_module_name, cb);
};
// Expose old module installation method for testing purpose
Modularizer.installModuleV1 = ModularizerV1.installModule;
Modularizer.getAdditionalConf = function(app_name) {
if (!app_name) throw new Error('No app_name defined');
var module_conf = Configuration.getAllSync();
var additional_env = {};
if (!module_conf[app_name]) {
additional_env = {};
additional_env[app_name] = {};
}
else {
additional_env = Common.clone(module_conf[app_name]);
additional_env[app_name] = JSON.stringify(module_conf[app_name]);
}
return additional_env;
};
/**
* Publish a module
*/
@ -522,44 +458,45 @@ Modularizer.generateSample = function(app_name, cb) {
rl.question(cst.PREFIX_MSG_MOD + "Module name: ", function(module_name) {
samplize(module_name);
});
};
function isValidModule(conf) {
var valid = true;
function installLangModule(module_name, cb) {
var node_module_path = path.resolve(path.join(__dirname, '../../../'));
Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[NPM]') + ' to install ' + module_name + ' ...');
if (!conf.apps) {
Common.printError(cst.PREFIX_MSG_MOD_ERR + 'apps attribute indicating the script to launch is not defined in the package.json');
return false;
}
var install_instance = spawn(cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error'], {
stdio : 'inherit',
env: process.env,
shell : true,
cwd : node_module_path
});
if (Array.isArray(conf.apps)) {
conf.apps.forEach(function(app) {
if (!app.script)
valid = false;
});
}
else {
if (!conf.apps.script)
valid = false;
}
install_instance.on('close', function(code) {
if (code > 0)
return cb(new Error('Module install failed'));
return cb(null);
});
return valid;
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
};
function moduleExist(module_name) {
var modules = getModuleInstalled();
function moduleExist(CLI, module_name, cb) {
// If old module, force his deletion
var modules_v1 = Configuration.getSync('module-db');
if (module_name.indexOf('/') > -1)
module_name = module_name.split('/')[1];
if (modules_v1) {
modules_v1 = Object.keys(modules_v1);
if (modules_v1.indexOf(module_name) > -1) {
return uninstallModule(CLI, module_name, function() {
cb(false);
});
}
}
return modules.indexOf(module_name) > -1 ? true : false;
var modules = Configuration.getSync(MODULE_CONF_PREFIX);
if (!modules) return cb(false);
modules = Object.keys(modules);
return cb(modules.indexOf(module_name) > -1 ? true : false);
};
function getModuleInstalled() {
shelljs.config.silent = true;
var module_folder = p.join(cst.PM2_ROOT_PATH, 'node_modules');
var modules = shelljs.ls('-A', module_folder);
shelljs.config.silent = false;
return modules;
}

View File

@ -0,0 +1,182 @@
/**
* Copyright 2013 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var shelljs = require('shelljs');
var path = require('path');
var fs = require('fs');
var async = require('async');
var p = path;
var spawn = require('child_process').spawn;
var chalk = require('chalk');
var Configuration = require('../../Configuration.js');
var cst = require('../../../constants.js');
var Common = require('../../Common');
var Utility = require('../../Utility.js');
var MODULE_CONF_PREFIX = 'module-db';
var Modularizer = module.exports = {};
function startModule(CLI, opts, cb) {
/** SCRIPT
* Open file and make the script detection smart
*/
if (!opts.cmd) throw new Error('module package.json not defined');
if (!opts.development_mode) opts.development_mode = false;
try {
var package_json = require(opts.cmd);
} catch(e) {
Common.printError(e);
return cb();
}
/**
* Script file detection
* 1- *apps* field (default pm2 json configuration)
* 2- *bin* field
* 3- *main* field
*/
if (!package_json.apps) {
package_json.apps = {};
if (package_json.bin) {
var bin = Object.keys(package_json.bin)[0];
package_json.apps.script = package_json.bin[bin];
}
else if (package_json.main) {
package_json.apps.script = package_json.main;
}
}
Common.extend(opts, {
cwd : opts.proc_path,
watch : opts.development_mode,
force_name : package_json.name,
started_as_module : true
});
// Start the module
CLI.start(package_json, opts, function(err, data) {
if (err) return cb(err);
return cb(null, data);
});
};
Modularizer.launchModules = function(CLI, cb) {
var module_folder = p.join(cst.PM2_ROOT_PATH, 'node_modules');
var modules = Configuration.getSync(MODULE_CONF_PREFIX);
if (!modules) return cb();
async.eachLimit(Object.keys(modules), 1, function(module, next) {
var pmod = p.join(module_folder, module, cst.DEFAULT_MODULE_JSON);
Common.printOut(cst.PREFIX_MSG_MOD + 'Starting module ' + module);
var opts = {};
if (modules[module] != true) {
Common.extend(opts, modules[module]);
}
Common.extend(opts, {
cmd : pmod,
development_mode : false,
proc_path : p.join(module_folder, module)
});
startModule(CLI, opts, function(err, dt) {
if (err) console.error(err);
return next();
});
}, function() {
return cb ? cb(null) : false;
});
}
Modularizer.installModule = function(CLI, module_name, opts, cb) {
var proc_path = '',
cmd = '',
conf = {},
development_mode = false;
var cli = {
bin : 'npm',
cmd : 'install'
}
Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[' + cli.bin.toUpperCase() + ']') + ' to install ' + module_name + ' ...');
var install_instance = spawn(cst.IS_WINDOWS ? cli.bin + '.cmd' : cli.bin, [cli.cmd, module_name, '--loglevel=error'], {
stdio : 'inherit',
env: process.env,
shell : true,
cwd : cst.PM2_ROOT_PATH
});
install_instance.on('close', finalize);
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
function finalize(code) {
if (code != 0) {
return cb(new Error("Installation failed"));
}
Common.printOut(cst.PREFIX_MSG_MOD + 'Module downloaded');
var canonic_module_name = Utility.getCanonicModuleName(module_name);
proc_path = p.join(cst.PM2_ROOT_PATH, 'node_modules', canonic_module_name);
cmd = p.join(proc_path, cst.DEFAULT_MODULE_JSON);
/**
* Append default configuration to module configuration
*/
try {
var conf = JSON.parse(fs.readFileSync(path.join(proc_path, 'package.json')).toString()).config;
if (conf) {
Object.keys(conf).forEach(function(key) {
Configuration.setSyncIfNotExist(canonic_module_name + ':' + key, conf[key]);
});
}
} catch(e) {
Common.printError(e);
}
opts = Common.extend(opts, {
cmd : cmd,
development_mode : development_mode,
proc_path : proc_path
});
Configuration.set(MODULE_CONF_PREFIX + ':' + canonic_module_name, {
uid : opts.uid,
gid : opts.gid,
version : 0
}, function(err, data) {
startModule(CLI, opts, function(err, dt) {
if (err) return cb(err);
if (process.env.PM2_PROGRAMMATIC === 'true')
return cb(null, dt);
CLI.conf(canonic_module_name, function() {
Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
Common.printOut(cst.PREFIX_MSG_MOD + 'Edit configuration via: `pm2 conf`');
return cb(null, dt);
});
});
});
}
}

View File

@ -21,6 +21,7 @@ var Utility = require('../../Utility.js');
var MODULE_CONF_PREFIX = 'module-db';
var Modularizer = require('./Modularizer.js');
var ModularizerV1 = require('./Modularizerv1.js');
// Special module with post display
function postDisplay(app, cb) {
@ -78,6 +79,25 @@ module.exports = function(CLI) {
opts = {};
}
// Because for test, allow to install module in V1 way
if (opts.v1) {
Common.printOut('Installing the V1 way...');
console.log(opts.uid, opts.gid, opts.v1);
ModularizerV1.installModule(this, module_name, opts, function(err, data) {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + (err.message || err));
return cb ? cb(Common.retErr(err)) : that.speedList(cst.ERROR_EXIT);
}
// Check if special module with post_install display
if (data && data[0] && data[0].pm2_env && data[0].pm2_env.PM2_EXTRA_DISPLAY) {
return postDisplay.call(that, data[0].pm2_env, cb);
}
return cb ? cb(null, data) : that.speedList(cst.SUCCESS_EXIT);
});
return false;
}
Modularizer.install(this, module_name, opts, function(err, data) {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + (err.message || err));

View File

@ -45,7 +45,7 @@ module.exports = function(PM2_HOME) {
DEFAULT_PID_PATH : p.resolve(PM2_HOME, 'pids'),
DEFAULT_LOG_PATH : p.resolve(PM2_HOME, 'logs'),
DEFAULT_MODULE_PATH : p.resolve(PM2_HOME, 'node_modules'),
DEFAULT_MODULE_PATH : p.resolve(PM2_HOME, 'modules'),
KM_ACCESS_TOKEN : p.resolve(PM2_HOME, 'km-access-token'),
DUMP_FILE_PATH : p.resolve(PM2_HOME, 'dump.pm2'),
DUMP_BACKUP_FILE_PATH : p.resolve(PM2_HOME, 'dump.pm2.bak'),

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
SRC=$(cd $(dirname "$0"); pwd)
source "${SRC}/include.sh"
echo -e "\033[1mRunning tests:\033[0m"
cd $file_path
#
# Re init module system
#
rm -rf ~/.pm2/node_modules
rm -rf ~/.pm2/modules
$pm2 kill
#
#
#
$pm2 install pm2-probe --v1

View File

@ -24,7 +24,7 @@ function spec {
success "$1"
}
$pm2 uninstall all
# if [ $TRAVIS ]
# then
@ -77,6 +77,8 @@ mocha --opts ./mocha.opts ./send_data_process.mocha.js
spec "Send data to a process"
mocha --opts ./mocha.opts ./modules.mocha.js
spec "Module API testing"
mocha --opts ./mocha.opts ./module_retrocompat.mocha.js
spec "Module retrocompatibility system"
mocha --opts ./mocha.opts ./json_validation.mocha.js
spec "JSON validation test"

View File

@ -0,0 +1,104 @@
var PM2 = require('../..');
var should = require('should');
var shelljs = require('shelljs');
var path = require('path');
var fs = require('fs');
describe('Modules programmatic testing', function() {
var pm2;
// after(function(done) {
// pm2.kill(done);
// });
var MODULE_CONF_PATH;
var MODULE_PATH;
it('should instanciate PM2', function() {
pm2 = new PM2.custom({
//independent : true,
//daemon_mode : true
});
MODULE_CONF_PATH = pm2._conf.PM2_MODULE_CONF_FILE;
MODULE_PATH = pm2._conf.DEFAULT_MODULE_PATH;
});
it('should cleanup paths', function() {
fs.writeFileSync(MODULE_CONF_PATH, '{}');
shelljs.rm('-r', MODULE_PATH);
shelljs.rm('-r', path.join(pm2._conf.PM2_HOME, 'node_modules'));
});
describe('Be able to manage old module system', function() {
it('should install a module the old school way', function(done) {
pm2.install('pm2-server-monit', { v1 : true}, function(err, apps) {
var data = JSON.parse(fs.readFileSync(MODULE_CONF_PATH));
should.exists(data['module-db']['pm2-server-monit']);
fs.statSync(path.join(pm2._conf.PM2_HOME, 'node_modules', 'pm2-server-monit'));
done();
});
});
it('should be able to uninstall module', function(done) {
pm2.uninstall('pm2-server-monit', function(err, apps) {
var data = JSON.parse(fs.readFileSync(MODULE_CONF_PATH));
should.not.exists(data['module-db']['pm2-server-monit']);
try {
fs.statSync(path.join(pm2._conf.PM2_HOME, 'node_modules', 'pm2-server-monit'));
} catch(e) {
if (!e) done(new Error('module must have been deleted...'));
}
done();
});
});
});
describe('Upgrade module to V2 management', function() {
it('should install a module the old school way', function(done) {
pm2.install('pm2-server-monit', { v1 : true}, function(err, apps) {
var data = JSON.parse(fs.readFileSync(MODULE_CONF_PATH));
should.exists(data['module-db']['pm2-server-monit']);
fs.statSync(path.join(pm2._conf.PM2_HOME, 'node_modules', 'pm2-server-monit'));
done();
});
});
it('should update and still have module started', function(done) {
pm2.update(function() {
pm2.list(function(err, procs) {
should(procs.length).eql(1);
done();
});
});
});
it('should reinstall module in new school way', function(done) {
pm2.install('pm2-server-monit', function(err, apps) {
var data = JSON.parse(fs.readFileSync(MODULE_CONF_PATH));
should.exists(data['module-db-v2']['pm2-server-monit']);
should.not.exists(data['module-db']['pm2-server-monit']);
try {
fs.statSync(path.join(pm2._conf.PM2_HOME, 'node_modules', 'pm2-server-monit'));
} catch(e) {
if (!e)
done(new Error('The old module has not been deleted...'));
}
fs.statSync(path.join(MODULE_PATH, 'pm2-server-monit', 'node_modules', 'pm2-server-monit'));
done();
});
});
it('should update and still have module started', function(done) {
pm2.update(function() {
pm2.list(function(err, procs) {
should(procs.length).eql(1);
done();
});
});
});
});
});