tsmith/node-control — pull request #12 by osher (2014-03-27 09:53:03+00:00)
Title: Facilitate collecting data from stderr and stdout

The change collects output spat to stderr and stdout so it can be used by the callback / exit callback.

I recommend to keep the `callback` and `exitCallback` with same signature to be compatible with the usage-pattern of libs such as async.

Assume the following user code:

```
var path = require('path')
, async = require('async')
, log = require('log4js').getLogger('zipper util')
, controller = Object.create(require('control').controller)
, ssh = controller.ssh
, argv = process.argv
, tmpDir = "/tmp/usr/zip/"
, packName
, packPath
, tmpZipDir
, source
;

if (argv[0] == 'node') argv.shift(); //throw 'node'
argv.shift(); //throw the script name

controller.address = argv.shift()

packName = argv.shift();
if (!packName) throw new Error('package name must be provided');

tmpZipDir = path.join(tmpDir, packName);
packPath = path.join( tmpDir, packName ) + ".zip"

async.waterfall(
[ function mkdir_tmp(done) {
step = 'mkdir';
log.debug('creating archive folder');
ssh('mkdir -p ' + tmpZipDir, done, done);
}
, function copying(done) {
step = 'copying';
log.debug('copying files from ' + source);
ssh('cp ' + source + ' ' + tmpZipDir , done, done);
}
, function archive(done) {
step = 'archiving';
log.debug('creating archive');
ssh('zip -r " + packPath + " " + tmpZipDir + "/*', done, done);
}
, function store(done) {
step = 'store on s3 through s3-fuse';
log.debug('storing archive on fixture-storage');
ssh('mv ' + packPath + " /mnt/s3/archives", done, done);
}
, function cleanup_db(done) {
step = 'cleanup';
log.debug('cleaning up temp');
ssh("rm -f -r " + tmpZipDir , done, done);
}
]
, function(err, std) {

/***********************************************
AND NOW - when something is wrong
any communication passed in this failed step will be in
(in addition to err to be the exit-code)

std.err //returns data gathered in stderr during the failed / last command
std.out //returns data gathered in stdout during the failed / last command
***********************************************/

}
)

```

basically, we're creating instrumentation that allows the programmer focus just on the commands he needs to use, so the example above is already pesudo code.

the end code looks better like:
```
task("magic", "do the magic", function(controller, source, tmpZipDir) {
var packPath = path.join( tmpDir, packName ) + ".zip";

require('./lib/scripter').run(controller
, { 'creating archive folder' : "mkdir -p " + tmpZipDir
, 'copying files' : "cp " + source + " " + tmpZipDir
, 'creating archive' : "zip -r " + packPath + " " + tmpZipDir + "/*"
, 'storing on s3-fuse' : "mv " + packPath + " /mnt/s3/archives"
, 'cleanup' : "rm -f -r " + tmpZipDir
}
, function(errCode, step, std ) {
/***********************************************
AND NOW - i hope you see where it's going
;-)
***********************************************/
}
)
});
```

the proposed change will utilize us a lot.
we need it for both production code, and obviously unit-tests...