Skip to content

Commit

Permalink
Options attrs updatable via CLI and JSON - small refactor for program…
Browse files Browse the repository at this point in the history
…matic usage
  • Loading branch information
Unitech committed Mar 9, 2016
1 parent d94d1ef commit 3469b58
Show file tree
Hide file tree
Showing 17 changed files with 175 additions and 61 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@

### 1.0.3

- Rename process
- Update configuration by restarting (for both CLI and JSON)
- Refactor programmatic system

### 1.0.2

- [#1035 #1055] Deactivate automatic dump on startup scripts
Expand Down
53 changes: 46 additions & 7 deletions lib/CLI.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ CLI._startScript = function(script, opts, cb) {
Common.getProcessIdByName(script, function(err, ids) {
if (err && cb) return cb(err);
if (ids.length > 0) {
CLI._restart(script, function(err, list) {
CLI._restart(script, opts, function(err, list) {
if (err) return cb(err);
Common.printOut(cst.PREFIX_MSG + 'Process successfully started');
return cb(true, list);
Expand All @@ -192,23 +192,28 @@ CLI._startScript = function(script, opts, cb) {
function restartExistingProcessId(cb) {
if (isNaN(script)) return cb(null);

CLI._restart(script, function(err, list) {
CLI._restart(script, opts, function(err, list) {
if (err) return cb(err);
Common.printOut(cst.PREFIX_MSG + 'Process successfully started');
return cb(true, list);
});
}

/**
* Restart a process with the same full path
* Or start it
*/
function restartExistingProcessPath(cb) {
Satan.executeRemote('findByFullPath', path.resolve(process.cwd(), script), function(err, exec) {
if (err) return cb ? cb(new Error(err)) : Common.exitCli(cst.ERROR_EXIT);

if (exec && (exec[0].pm2_env.status == cst.STOPPED_STATUS ||
exec[0].pm2_env.status == cst.STOPPING_STATUS ||
exec[0].pm2_env.status == cst.ERRORED_STATUS)) {
// Restart process if stopped
var app_name = exec[0].pm2_env.name;

CLI._restart(app_name, function(err, list) {
CLI._restart(app_name, opts, function(err, list) {
if (err) return cb ? cb(new Error(err)) : Common.exitCli(cst.ERROR_EXIT);

Common.printOut(cst.PREFIX_MSG + 'Process successfully started');
Expand Down Expand Up @@ -1178,6 +1183,7 @@ CLI._operate = function(action_name, process_name, envs, cb) {
envs = {};
}

envs = CLI._handleAttributeUpdate(envs);

/**
* Operate action on specific process id
Expand All @@ -1188,9 +1194,15 @@ CLI._operate = function(action_name, process_name, envs, cb) {
if (action_name == 'restartProcessId') {
// I dont get why we did this
// env : process.env.PM2_PROGRAMMATIC === 'true' ? {} : util._extend(process.env, envs)
var new_env = util._extend({}, process.env);

Object.keys(envs).forEach(function(k) {
new_env[k] = envs[k];
});

opts = {
id : id,
env : util._extend(process.env, envs)
env : new_env
};
}

Expand Down Expand Up @@ -1279,19 +1291,46 @@ CLI.restart = function(cmd, opts, cb) {
cmd = cmd.toString();

if (cmd == "-") {
// Restart from PIPED JSON
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (param) {
process.stdin.pause();
CLI.actionFromJson('restartProcessId', param, opts, 'pipe', cb);
});
}
else if (typeof(cmd) === 'object' || cmd.indexOf('.json') > 0)
else if (typeof(cmd) === 'object' || cmd.indexOf('.json') > 0) {
// Restart a JSON
CLI.actionFromJson('restartProcessId', cmd, opts, 'file', cb);
else
CLI._restart(cmd, process.env, cb);
}
else {
CLI._restart(cmd, opts, cb);
}
}

CLI._handleAttributeUpdate = function(opts) {
// Underscorize camel case Commander.js options
var conf = Config.transCMDToConf(opts);

if (typeof(conf.name) != 'string')
delete conf.name;

var argsIndex = 0;
if (opts.rawArgs && (argsIndex = opts.rawArgs.indexOf('--')) >= 0)
conf.args = opts.rawArgs.slice(argsIndex + 1);

var appConf = verifyConfs(conf)[0];

if (argsIndex == -1)
delete appConf.args;
if (appConf.name == 'undefined')
delete appConf.name;

delete appConf.exec_mode;

return appConf;
};

CLI._restart = function(cmd, envs, cb) {
CLI._operate('restartProcessId', cmd, envs, cb);
}
Expand Down
53 changes: 37 additions & 16 deletions lib/Common.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
// "maintainers": [
// {
// "name": "Garen J. Torikian",
// "email": "gjtorikian@gmail.com"
// }
// ],
// "repository": {
// "type": "git",
// "url": "git+https://github.com/gjtorikian/isBinaryFile.git"
// },
/**
* @file Common utilities
* @project PM2
*/

/**
* Module dependencies
Expand Down Expand Up @@ -115,9 +109,20 @@ Common.prepareAppConf = function(app, outputter) {

// Set current env by first adding the process environment and then extending/replacing it
// with env specified on command-line or JSON file.
app.env = [{}, process.env, app.env || {}, {pm_cwd: cwd}].reduce(function(e1, e2){
return util._extend(e1, e2);
});

if (process.env.PM2_PROGRAMMATIC) {
var normalized_env = {};
Common.safeExtend(normalized_env, process.env);
//console.log(normalized_env);
app.env = [{}, normalized_env, app.env || {}, {pm_cwd: cwd}].reduce(function(e1, e2){
return util._extend(e1, e2);
});
}
else {
app.env = [{}, process.env, app.env || {}, {pm_cwd: cwd}].reduce(function(e1, e2){
return util._extend(e1, e2);
});
}

app.pm_cwd = cwd;

Expand Down Expand Up @@ -399,12 +404,28 @@ Common.getProcessByName = function(name, cb) {
});
};

Common.extend = function(origin, add){
// Don't do anything if add isn't an object
/**
* Raw extend
*/
Common.extend = function(destination, source){
if (!source || typeof source != 'object') return destination;

Object.keys(source).forEach(function(new_key) {
if (source[new_key] != '[object Object]')
destination[new_key] = source[new_key];
});

return destination;
};

/**
* This is useful when starting script programmatically
*/
Common.safeExtend = function(origin, add){
if (!add || typeof add != 'object') return origin;

//Ignore PM2's set environment variables from the nested env
var keysToIgnore = ['name', 'exec_mode', 'env', 'args', 'pm_cwd', 'exec_interpreter', 'pm_exec_path', 'node_args', 'pm_out_log_path', 'pm_err_log_path', 'pm_pid_path', 'pm_id', 'status', 'pm_uptime', 'created_at', 'started_inside', 'unstable_restarts', 'restart_time', 'pm_id', 'axm_actions', 'pmx_module', 'command', 'watch', 'versioning', 'vizion_runing', 'MODULE_DEBUG'];
var keysToIgnore = ['name', 'exec_mode', 'env', 'args', 'pm_cwd', 'exec_interpreter', 'pm_exec_path', 'node_args', 'pm_out_log_path', 'pm_err_log_path', 'pm_pid_path', 'pm_id', 'status', 'pm_uptime', 'created_at', 'unstable_restarts', 'restart_time', 'pm_id', 'axm_actions', 'pmx_module', 'command', 'watch', 'versioning', 'vizion_runing', 'MODULE_DEBUG'];

var keys = Object.keys(add);
var i = keys.length;
Expand Down
18 changes: 5 additions & 13 deletions lib/God.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ require('./Watcher')(God);
*/
God.executeApp = function executeApp(env, cb) {
var env_copy = Common.clone(env);
var startingInside = (env_copy['env'] && env_copy['env']['pm_id'] && !env_copy['started_inside']) ? true : false;

Common.extend(env_copy, env_copy.env);

Expand All @@ -81,11 +80,10 @@ God.executeApp = function executeApp(env, cb) {
* 3 - Assign a log file name depending on the id
* 4 - If watch option is set, look for changes
*/
if (env_copy['pm_id'] === undefined || startingInside) {
if (env_copy['pm_id'] === undefined) {
env_copy['pm_id'] = God.getNewId();
env_copy['restart_time'] = 0;
env_copy['unstable_restarts'] = 0;
env_copy['started_inside'] = startingInside;

env_copy['command'] = {
locked : false,
Expand Down Expand Up @@ -336,14 +334,7 @@ God.handleExit = function handleExit(clu, exit_code, kill_signal) {
};

/**
* First step before execution
* Check if the -i parameter has been passed
* so we execute the app multiple time
* @api public
* @method prepare
* @param {Mixed} env
* @param {} cb
* @return Literal
* Init new process
*/
God.prepare = function prepare(env, cb) {
// If instances option is set (-i [arg])
Expand All @@ -363,9 +354,10 @@ God.prepare = function prepare(env, cb) {
}

env.NODE_APP_INSTANCE = instance_id++;

env.vizion_running = false;
if (env.env && env.env.vizion_running) env.env.vizion_running = false;

if (env.env && env.env.vizion_running)
env.env.vizion_running = false;

return God.executeApp(Common.clone(env), function(err, clu) {
if (err) return ex(i - 1);
Expand Down
6 changes: 2 additions & 4 deletions lib/God/Reload.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,7 @@ module.exports = function(God) {
else {
console.log('Process in a stopped status, starting it');
return God.restartProcessId({
id : id,
env : God.clusters_db[id].pm2_env
id : id
}, cb);
}
};
Expand All @@ -196,8 +195,7 @@ module.exports = function(God) {
else {
console.log('Process in a stopped status, starting it');
return God.restartProcessId({
id : id,
env : God.clusters_db[id].pm2_env
id : id
}, cb);
}
};
Expand Down
18 changes: 6 additions & 12 deletions lib/Log.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ Log.stream = function(id, raw, timestamp, exclusive) {

CLI.launchBus(function(err, bus) {

bus.on('log:*', function(type, packet) {
bus.on('log:*', function(type, data) {
if (id !== 'all'
&& packet.process.name != id
&& packet.process.pm_id != id)
&& data.process.name != id
&& data.process.pm_id != id)
return;

if ((type === 'out' && exclusive === 'err')
Expand All @@ -93,18 +93,12 @@ Log.stream = function(id, raw, timestamp, exclusive) {
if (type === 'PM2' && raw)
return;

var name = packet.process.name + '-' + packet.process.pm_id;

var lines;

if (typeof(packet.data) === 'string')
lines = (packet.data || '').split('\n');
else
return;
var name = data.process.name + '-' + data.process.pm_id;
var lines = (data.data || '').split('\n');

lines.forEach(function(line) {
if (!line) {
return;
return;
}

if (!raw) {
Expand Down
3 changes: 1 addition & 2 deletions lib/Worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ module.exports = function(God) {
console.log('[PM2][WORKER] Process %s restarted because it uses 0 memory and has ONLINE status',
proc.pm2_env.pm_id);
God.restartProcessId({
id: proc.pm2_env.pm_id,
env: proc.pm2_env.env
id: proc.pm2_env.pm_id
}, function(err, data) {
if (err)
console.error(err.stack || err);
Expand Down
48 changes: 48 additions & 0 deletions test/bash/app_config_update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash

SRC=$(cd $(dirname "$0"); pwd)
source "${SRC}/include.sh"

echo -e "\033[1mRunning tests:\033[0m"

cd $file_path

$pm2 kill

$pm2 start app-config-update/args1.json
$pm2 prettylist | grep "node_args: \[\]"
spec "Should application have empty node argument list"

$pm2 restart app-config-update/args2.json
$pm2 prettylist | grep "node_args: \[ '--harmony' \]"
spec "Should application have one node argument"

$pm2 delete all

$pm2 start app-config-update/echo.js
$pm2 prettylist | grep "node_args: \[\]"
spec "Should application have empty node argument list"

$pm2 restart app-config-update/echo.js --node-args="--harmony"
$pm2 prettylist | grep "node_args: \[ '--harmony' \]"
spec "Should application have one node argument"

# Variation with pm2 start that restarts an app
$pm2 start echo --node-args="--harmony --harmony-proxies"
$pm2 prettylist | grep "node_args: \[ '--harmony', '--harmony-proxies' \]"
spec "Should application have one node argument"

#
# Rename
#
$pm2 restart 0 --name="new-name"
$pm2 reset all
$pm2 restart new-name
should 'should restart processes with new name' 'restart_time: 1' 1

$pm2 start 0 --name="new-name-2"
$pm2 reset all
$pm2 restart new-name-2
should 'should restart processes with new name' 'restart_time: 1' 1

$pm2 delete all
4 changes: 4 additions & 0 deletions test/fixtures/app-config-update/args1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"script" : "echo.js",
"node_args" : ""
}
4 changes: 4 additions & 0 deletions test/fixtures/app-config-update/args2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"script" : "echo.js",
"node_args" : "--harmony"
}
7 changes: 7 additions & 0 deletions test/fixtures/app-config-update/echo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

var i = 0;
setInterval(function() {
console.log('ok', i++);
}, 2000);

console.log('ok');
2 changes: 1 addition & 1 deletion test/fixtures/env-refreshed.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[{
"name" : "env",
"name" : "appname",
"script" : "./env.js",
"out_file" : "out-env.log",
"merge_logs" : true,
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/env.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[{
"name" : "env",
"name" : "appname",
"script" : "./env.js",
"out_file" : "out-env.log",
"merge_logs" : true,
Expand Down

0 comments on commit 3469b58

Please sign in to comment.