mecano
Version:
Common functions for system deployment.
221 lines (207 loc) • 6.92 kB
JavaScript
// Generated by CoffeeScript 1.7.1
var Ftp, child, conditions, curl, each, execute, fs, misc, move, remove, request, url;
fs = require('ssh2-fs');
url = require('url');
Ftp = require('jsftp');
each = require('each');
request = require('request');
curl = require('./misc/curl');
misc = require('./misc');
conditions = require('./misc/conditions');
child = require('./misc/child');
execute = require('./execute');
remove = require('./remove');
move = require('./move');
module.exports = function(goptions, options, callback) {
var finish, result, _ref;
_ref = misc.args(arguments), goptions = _ref[0], options = _ref[1], callback = _ref[2];
result = child();
finish = function(err, downloaded) {
if (callback) {
callback(err, downloaded);
}
return result.end(err, downloaded);
};
return misc.options(options, function(err, options) {
var downloaded;
if (err) {
return finish(err);
}
downloaded = 0;
return each(options).parallel(goptions.parallel).on('item', function(options, next) {
var checksum, destination, download, md5sum, prepare, source, stageDestination, unstage;
destination = options.destination, source = options.source, md5sum = options.md5sum;
if (!source) {
return next(new Error("Missing source: " + source));
}
if (!destination) {
return next(new Error("Missing destination: " + destination));
}
if (options.force == null) {
options.force = false;
}
stageDestination = "" + destination + "." + (Date.now()) + (Math.round(Math.random() * 1000));
prepare = function() {
if (typeof options.log === "function") {
options.log("Check if destination exists");
}
return fs.exists(options.ssh, destination, function(err, exists) {
if (options.force) {
return download();
} else if (exists && md5sum) {
return misc.file.hash(options.ssh, destination, 'md5', function(err, hash) {
if (err) {
return next(err);
}
if (hash === md5sum) {
return next();
}
return fs.unlink(options.ssh, destination, function(err) {
if (err) {
return next(err);
}
return download();
});
});
} else if (exists) {
return download();
} else {
return download();
}
});
};
download = function() {
var cmd, u;
if (typeof options.log === "function") {
options.log("Download the source");
}
u = url.parse(source);
if (options.ssh) {
if (u.protocol === 'http:') {
cmd = "curl " + source + " -o " + stageDestination;
cmd += " -s";
if (options.proxy) {
cmd += " -x " + options.proxy;
}
return execute({
ssh: options.ssh,
cmd: cmd,
log: options.log,
stdout: options.stdout,
stderr: options.stderr
}, function(err, executed, stdout, stderr) {
if (err) {
return next(curl.error(err));
}
return checksum();
});
} else if (u.protocol === 'ftp:') {
return next(new Error('FTP download not supported over SSH'));
} else {
return fs.createReadStream(options.ssh, u.pathname, function(err, rs) {
if (err) {
return next(err);
}
return fs.createWriteStream(null, stageDestination, function(err, ws) {
if (err) {
return next(err);
}
return rs.pipe(ws).on('close', function() {
return checksum();
}).on('error', next);
});
});
}
} else {
return fs.createWriteStream(null, stageDestination, function(err, ws) {
var ftp, pass, user, _ref1;
if (err) {
return next(err);
}
if (u.protocol === 'http:') {
options.url = source;
request(options).pipe(ws);
} else if (u.protocol === 'ftp:') {
if (options.host == null) {
options.host = u.hostname;
}
if (options.port == null) {
options.port = u.port;
}
if (u.auth) {
_ref1 = u.auth.split(':'), user = _ref1.user, pass = _ref1.pass;
}
if (options.user == null) {
options.user = user;
}
if (options.pass == null) {
options.pass = pass;
}
ftp = new Ftp(options);
ftp.getGetSocket(u.pathname, function(err, rs) {
if (err) {
return next(err);
}
rs.pipe(ws);
return rs.resume();
});
} else {
fs.createReadStream(null, u.pathname, function(err, rs) {
return rs.pipe(ws);
});
}
ws.on('close', function() {
return checksum();
});
return ws.on('error', function(err) {
return remove(ws, function(err) {
return next(err);
});
});
});
}
};
checksum = function() {
if (!md5sum) {
return unstage();
}
if (typeof options.log === "function") {
options.log("Compare the downloaded file with the user-provided checksum");
}
return misc.file.hash(options.ssh, stageDestination, 'md5', function(err, hash) {
if (hash === md5sum) {
return unstage();
}
return misc.file.remove(options.ssh, stageDestination, function(err) {
if (err) {
return next(err);
}
return next(new Error("Invalid checksum, found \"" + hash + "\" instead of \"" + md5sum + "\""));
});
});
};
unstage = function() {
if (typeof options.log === "function") {
options.log("Move the downloaded file");
}
return move({
ssh: options.ssh,
source: stageDestination,
destination: destination,
source_md5: md5sum
}, function(err, moved) {
if (err) {
return next(err);
}
if (moved) {
downloaded++;
}
return next();
});
};
return prepare();
}).on('both', function(err) {
return finish(err, downloaded);
});
});
};