tug
Version:
tug at the heart of your deployment process
162 lines (133 loc) • 4.95 kB
JavaScript
// Generated by CoffeeScript 1.10.0
(function() {
var _key, _val, argv, argv_hosts, argv_steps, async, coerceSshconfHost, connectToHost, fs, i, key_matched, len, levenshtein, line, local_tugfile_filename, makeStepScript, minimist, path, resolvePath, ssh, tugfile, tugfile_distances, tugfile_filename, tugfile_keys, tugfile_lines, tugfile_name, tugfiles_available,
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; };
fs = require('fs');
path = require('path');
minimist = require('minimist');
async = require('async');
ssh = require('sshconf-stream');
argv = minimist(process.argv.slice(2));
resolvePath = function(string) {
if (string.substr(0, 1) === '~') {
string = process.env.HOME + string.substr(1);
}
return path.resolve(string);
};
tugfile_name = argv._[0];
tugfile_filename = resolvePath("~/.tug/" + tugfile_name + ".tug");
local_tugfile_filename = resolvePath("./.tug");
if (!tugfile_name && fs.existsSync(local_tugfile_filename)) {
tugfile_filename = local_tugfile_filename;
} else if (!fs.existsSync(tugfile_filename)) {
levenshtein = require('levenshtein');
tugfiles_available = fs.readdirSync(resolvePath("~/.tug/"));
tugfile_distances = tugfiles_available.map(function(f) {
return {
filename: f.split('.')[0],
distance: levenshtein(tugfile_name, f.slice(0, +(tugfile_name.length - 1) + 1 || 9e9))
};
});
tugfile_distances.sort(function(a, b) {
return a.distance - b.distance;
});
console.log("Tugfile not found. Did you mean `tug " + tugfile_distances[0].filename + "`?");
process.exit();
}
tugfile = {};
tugfile_keys = [];
tugfile_lines = fs.readFileSync(tugfile_filename).toString().trim().split('\n');
_key = null;
_val = '';
for (i = 0, len = tugfile_lines.length; i < len; i++) {
line = tugfile_lines[i];
if (key_matched = line.match(/^\[(.+)\]$/)) {
if ((_key != null) && (_val != null)) {
tugfile_keys.push(_key);
tugfile[_key] = _val.trim();
}
_val = '';
_key = key_matched[1];
} else {
if (_key != null) {
_val += line + '\n';
}
}
}
if ((_key != null) && (_val != null)) {
tugfile_keys.push(_key);
tugfile[_key] = _val.trim();
}
makeStepScript = function(step_name) {
return tugfile['step ' + step_name].trim().split('\n').join(' && ');
};
tugfile.steps = tugfile_keys.filter(function(k) {
return k.slice(0, 4) === 'step';
}).map(function(s) {
return s.slice(5);
});
tugfile.hosts = tugfile.hosts.trim().split('\n');
if ((argv.hosts != null) || (argv.h != null)) {
argv_hosts = (argv.hosts || argv.h).split(',');
tugfile.hosts = tugfile.hosts.filter(function(h) {
return indexOf.call(argv_hosts, h) >= 0;
});
}
if (argv.all || argv.a) {
} else if (argv_steps = argv.steps || argv.step || argv.s) {
argv_steps = argv_steps.split(',');
tugfile.steps = tugfile.steps.filter(function(s) {
return indexOf.call(argv_steps, s) >= 0;
});
} else {
tugfile.steps = tugfile.steps.slice(0, 1);
}
fs.createReadStream(resolvePath('~/.ssh/config')).pipe(ssh.createParseStream()).on('data', function(_host_data) {
var host_data, ref;
host_data = coerceSshconfHost(_host_data);
if (ref = host_data.host, indexOf.call(tugfile.hosts, ref) >= 0) {
return connectToHost(host_data);
}
});
coerceSshconfHost = function(host_data) {
var coerced_host_data, k, ref, v;
coerced_host_data = {};
ref = host_data.keywords;
for (k in ref) {
v = ref[k];
coerced_host_data[k.toLowerCase()] = v[0];
}
return coerced_host_data;
};
connectToHost = function(host_data) {
var privateKey, privateKeyFilename, ssh_conn;
privateKeyFilename = host_data.identityfile || '~/.ssh/id_rsa';
privateKey = require('fs').readFileSync(resolvePath(privateKeyFilename));
ssh_conn = new require('ssh2')();
ssh_conn.connect({
host: host_data.hostname,
username: host_data.user || process.env.USER,
privateKey: privateKey
});
return ssh_conn.on('ready', function() {
return async.mapSeries(tugfile.steps, function(s, _cb) {
var step_script;
step_script = makeStepScript(s);
return ssh_conn.exec(step_script, function(err, stream) {
var stream_output;
stream_output = '';
stream.on('data', function(data) {
return stream_output += data.toString();
});
return stream.on('exit', function() {
console.log("[" + host_data.host + "] " + s + "\n> " + step_script + "\n" + stream_output);
return _cb();
});
});
}, function() {
return ssh_conn.end();
});
});
};
}).call(this);