UNPKG

mecano

Version:

Common functions for system deployment.

330 lines (321 loc) 11.5 kB
// Generated by CoffeeScript 1.9.1 var Ftp, curl, fs, misc, path, request, url, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, slice = [].slice; module.exports = function(options, callback) { var algo, destination, do_cache, do_checksum, do_download, do_local_md5, do_prepare, hash, protocols_ftp, protocols_http, ref, ref1, source, stageDestination, unstage; destination = options.destination, source = options.source; if (!source) { return callback(new Error("Missing source: " + source)); } if (!destination) { return callback(new Error("Missing destination: " + destination)); } stageDestination = destination + "." + (Date.now()) + (Math.round(Math.random() * 1000)); if (options.md5 != null) { if ((ref = typeof options.md5) !== 'string' && ref !== 'boolean') { return callback(new Error("Invalid MD5 Hash:" + options.md5)); } algo = 'md5'; hash = options.md5; } else if (options.sha1 != null) { if ((ref1 = typeof options.sha1) !== 'string' && ref1 !== 'boolean') { return callback(new Error("Invalid SHA-1 Hash:" + options.sha1)); } algo = 'sha1'; hash = options.sha1; } else { algo = 'md5'; hash = false; } protocols_http = ['http:', 'https:']; protocols_ftp = ['ftp:', 'ftps:']; do_cache = (function(_this) { return function() { var cache_file, cache_path; if (!((options.cache_dir != null) || (options.cache_file != null))) { return do_local_md5(); } if (options.cache_dir === false || options.cache_file === false) { return do_local_md5(); } if (typeof options.log === "function") { options.log("Mecano `download`: using cache [DEBUG]"); } cache_path = typeof options.cache_dir === 'string' ? options.cache_dir : './'; cache_file = typeof options.cache_file === 'string' ? options.cache_file : path.basename(options.source); cache_path = path.resolve(cache_path, cache_file); if (typeof options.log === "function") { options.log("Mecano `download`: cache path is '" + cache_path + "' [INFO]"); } return _this.download({ ssh: null, source: options.source, destination: cache_path, cache_dir: false, cache_file: false, md5: options.md5, sha1: options.sha1, force: options.force_cache }, function(err, cached) { var push_file_opt; if (err) { return callback(err); } if (typeof options.log === "function") { options.log(cached ? "Mecano `download`: cache updated [WARN]" : "Mecano `download`: cache not modified [INFO]"); } if (typeof options.log === "function") { options.log("Mecano `download`: sending cache to destination [DEBUG]"); } push_file_opt = { ssh: options.ssh, source: cache_path, destination: options.destination, cache_dir: false, cache_file: false, mode: options.mode, md5: options.md5, sha1: options.sha1, force: options.force, uid: options.uid, gid: options.gid, log: options.log, stdout: options.stdout, stderr: options.stderr }; if (hash) { return _this.download(push_file_opt, callback); } else { return misc.file.hash(null, cache_path, algo, function(err, calc_hash) { push_file_opt[algo] = calc_hash; return _this.download(push_file_opt, callback); }); } }); }; })(this); do_local_md5 = function() { var protocol; if (hash !== true) { return do_prepare(); } if (!options.ssh) { return callback(Error("Unsupported hash 'true' in non-ssh mode")); } protocol = url.parse(options.source).protocol; if (indexOf.call(slice.call(protocols_http).concat(slice.call(protocols_ftp)), protocol) >= 0) { return callback(Error("Unsupported hash 'true' with non-file protocols")); } return misc.file.hash(null, options.source, algo, function(err, l_hash) { if (err) { return callback(err); } hash = l_hash; return do_prepare(); }); }; do_prepare = (function(_this) { return function() { if (typeof options.log === "function") { options.log("Mecano `download`: Check if destination (" + destination + ") exists [DEBUG]"); } return fs.exists(options.ssh, destination, function(err, exists) { if (err) { return callback(err); } if (exists) { if (typeof options.log === "function") { options.log("Mecano `download`: destination exists [INFO]"); } if (options.force) { if (typeof options.log === "function") { options.log("Mecano `download`: Force download [DEBUG]"); } return do_download(); } else if (hash) { if (typeof options.log === "function") { options.log("Mecano `download`: comparing " + algo + " hash [DEBUG]"); } return misc.file.hash(options.ssh, destination, algo, function(err, c_hash) { if (err) { return callback(err); } if (hash === c_hash) { if (typeof options.log === "function") { options.log("Mecano `download`: Hashes match, skipping [DEBUG]"); } return callback(); } if (typeof options.log === "function") { options.log("Mecano `download`: Hashes don't match, delete then re-download [WARN]"); } return fs.unlink(options.ssh, destination, function(err) { if (err) { return callback(err); } return do_download(); }); }); } else { if (typeof options.log === "function") { options.log("Mecano `download`: destination exists, check disabled, skipping [DEBUG]"); } return callback(null, false); } } else { if (typeof options.log === "function") { options.log("Mecano `download`: destination doesn't exists, cheking parent directories (" + (path.join(destination, '..')) + ") [DEBUG]"); } return _this.mkdir({ destination: path.join(destination, '..') }, function(err, created) { if (err) { return callback(err); } if (created) { if (typeof options.log === "function") { options.log("Mecano `download`: Parent directory created [WARN]"); } } return do_download(); }); } }); }; })(this); do_download = (function(_this) { return function() { var cmd, k, ref2, ref3, u; if (typeof options.log === "function") { options.log("Mecano `download`: Download the source [DEBUG]"); } u = url.parse(source); if (options.ssh) { if (ref2 = u.protocol, indexOf.call(protocols_http, ref2) >= 0) { k = u.protocol === 'https:' ? '-k' : ''; cmd = "curl " + k + " -s " + source + " -o " + stageDestination; if (options.proxy) { cmd += " -x " + options.proxy; } return _this.execute({ cmd: cmd }, function(err, executed) { if (err) { return callback(curl.error(err)); } return do_checksum(); }); } else if (ref3 = u.protocol, indexOf.call(protocols_ftp, ref3) >= 0) { return callback(new Error('FTP download not supported over SSH')); } else { return fs.createWriteStream(options.ssh, stageDestination, function(err, ws) { if (err) { return callback(err); } return fs.createReadStream(null, u.pathname, function(err, rs) { if (err) { return callback(err); } rs.on('error', callback); return rs.pipe(ws).on('close', function() { return do_checksum(); }).on('error', callback); }); }); } } else { return fs.createWriteStream(null, stageDestination, function(err, ws) { var ftp, pass, ref4, ref5, ref6, user; if (err) { return callback(err); } if (ref4 = u.protocol, indexOf.call(protocols_http, ref4) >= 0) { options.url = source; request(options).pipe(ws); } else if (ref5 = u.protocol, indexOf.call(protocols_ftp, ref5) >= 0) { if (options.host == null) { options.host = u.hostname; } if (options.port == null) { options.port = u.port; } if (u.auth) { ref6 = u.auth.split(':'), user = ref6.user, pass = ref6.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 callback(err); } rs.pipe(ws); return rs.resume(); }); } else { fs.createReadStream(null, u.pathname, function(err, rs) { if (err) { return callback(err); } return rs.pipe(ws); }); } ws.on('close', function() { return do_checksum(); }); return ws.on('error', function(err) { return _this.remove({ ssh: null, destination: stageDestination }, callback); }); }); } }; })(this); do_checksum = function() { if (!hash) { return unstage(); } if (typeof options.log === "function") { options.log("Mecano `download`: Compare the downloaded file with the provided checksum [DEBUG]"); } return misc.file.hash(options.ssh, stageDestination, algo, function(err, calc_hash) { if (hash === calc_hash) { "Mecano `download`: download is valid [INFO]"; return unstage(); } return misc.file.remove(options.ssh, stageDestination, function(err) { if (err) { return callback(err); } return callback(new Error("Invalid checksum, found \"" + calc_hash + "\" instead of \"" + hash + "\"")); }); }); }; unstage = (function(_this) { return function() { if (typeof options.log === "function") { options.log("Mecano `download`: Move the downloaded file [DEBUG]"); } return _this.move({ source: stageDestination, destination: destination, source_md5: options.md5 }, callback); }; })(this); return do_cache(); }; fs = require('ssh2-fs'); Ftp = require('jsftp'); path = require('path'); request = require('request'); url = require('url'); misc = require('./misc'); curl = require('./misc/curl');