Files
deployd/bin/dpd
2012-04-17 08:49:42 -07:00

403 lines
9.8 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Dependencies
*/
var program = require('commander')
, dpd = require('../')
, fs = require('fs')
;
// Options
program
.version('0.3.0-pre')
.option('-j, --json', 'output as json')
.option('-p, --port <port>', 'specify the port (2403)')
.option('-s, --storage <url>', 'specify where to store resources (mongodb://localhost/deployd)')
.option('-d, --destination <url>', 'specify where to push to when cloning')
;
/**
* A method to output json.
*/
function json(obj) {
if(program && program.json) process.stdout.write(JSON.stringify(obj));
}
/**
* Silent if in json mode.
*/
function log() {
if(!program.json) console.log.apply(console, arguments);
}
/**
* List all administration keys (users).
*/
program
.command('keys')
.description(' - list all admin keys')
.action(function () {
var port = program.port || 2403;
if(program.storage) {
dpd.storage(program.storage);
}
dpd.use('http://localhost:' + port).use('/keys').get(function (err, keys) {
json(keys);
log(keys || 'no keys found! see dpd --help');
process.exit();
})
})
/**
* Add a new admin key.
*/
program
.command('addkey [key]')
.description(" - add a new admin key eg. dpd addkey '{\"user\": \"foo\", \"label\": \"admin\"}'")
.action(function (key) {
try {
key = JSON.parse(key);
} catch(e) {
key = undefined;
}
var strength = Math.floor(Math.random() * 5) + 2;
while(strength--) {
key[keygen()] = keygen() + keygen() + keygen();
}
if(typeof key == 'object') {
if(program.storage) {
dpd.storage(program.storage);
}
var port = program.port || 2403;
dpd.use('http://localhost:' + port).use('/keys').post(key, function (err, newKey) {
if(err) {
json(err);
log('Could not add key', err);
} else {
log('added key', newKey);
}
process.exit();
})
} else {
var msg = 'key must be a valid JSON object with more than one attribute!';
json(new Error(msg))
log(msg);
}
})
;
/**
* Keygen
*/
function keygen() {
// TODO added randomness
return Math.random().toString().split('.')[1];
}
/**
* Generate a key
*/
program
.command('key')
.description(" - generate, add, and print a random admin key")
.action(function () {
var port = program.port || 2403;
var key = {}, strength = Math.floor(Math.random() * 5) + 2;
while(strength--) {
key[keygen()] = keygen() + keygen() + keygen();
}
if(program.storage) {
dpd.storage(program.storage);
}
dpd.use('http://localhost:' + port).use('/keys').post(key, function (err, newKey) {
if(err) {
json(err);
log('Could not add key', err);
} else {
json(newKey);
log('added key:\n\n' + JSON.stringify(newKey) + '\n');
}
process.exit();
})
})
;
/**
* Remove an admin key by id.
*/
program
.command('rm [query]')
.description(' - remove an admin key by query')
.action(function (query) {
if(!query) return console.log('you must provide the _id of they key you want to remove');
// parse the query
query = JSON.parse(query);
if(program.storage) {
dpd.storage(program.storage);
}
if(Object.keys(query) < 1) throw 'use `dpd reset` to clear all keys';
var port = program.port || 2403;
dpd.use('http://localhost:' + port).use('/keys').del(query, function (err) {
if(err) {
json(err);
log(err);
} else {
json({removed: query});
log('removed all keys matching the given query');
}
process.exit();
})
});
/**
* Remove all admin keys.
*/
program
.command('reset')
.description(" - remove all admin keys by query (cannot be undone)'")
.action(function () {
if(program.storage) {
dpd.storage(program.storage);
}
var port = program.port || 2403;
dpd.use('http://localhost:' + port).use('/keys').del(function (err) {
if(err) {
json(err);
log(err);
} else {
json({removed: 'all'});
log('removed all keys');
}
process.exit();
})
});
/**
* Start the http server and listen.
*/
program
.command('listen')
.description(' - start listening over http at the provided port')
.action(function (cmd) {
var port = program.port || 2403;
if(program.storage) {
dpd.storage(program.storage);
}
dpd.use('http://localhost:' + port).listen(function () {
json({port: port, storage: dpd.storage()});
log('deployd is listening on port %s and storing resources at %s', port, dpd.storage());
});
})
;
/**
* Mount a file collection on the local file system.
*/
program
.command('mount [path]')
.description(" - mount a file collection on the local file system")
.action(function (path) {
var port = program.port || 2403;
if(program.storage) {
dpd.storage(program.storage);
}
var files = dpd.use('http://localhost:' + port).use(path);
var watching = {};
function watch(file, path) {
var fd = '.' + path + '/' + file;
if(watching[fd]) return;
watching[fd] = fs
.watch(fd, function (type, filename) {
if(type === 'change') {
// upload changed file
files
.use('/' + file)
.use(function (req, res, next) {
req.file = fs.createReadStream('.' + path + '/' + file)
req.file.pause();
next();
})
.post(function (err, res) {
console.log('uploaded', file);
})
;
}
})
.on('error', function (err) {
console.log(err);
})
;
}
files
.use(function (req, res, next) {
fs.exists('.' + path, function (exists) {
if(!exists) {
fs.mkdir('.' + path, function (err) {
next(err);
})
} else {
next();
}
})
})
.get(function (err, dir) {
if(err) console.error(err);
if(Array.isArray(dir)) {
dir.forEach(function (file) {
files
.use('/' + file)
.use(function (req, res, next) {
fs.exists('.' + path + '/' + file, function (exists) {
next(exists ? {file: require('path').resolve('.' + path + '/' + file), message: 'already exists'} : null);
});
})
.get({}, function (err, res) {
if(err) return console.log('.' + path + '/' + file, err.message, '- using local version');
console.log('downloading', '.' + path + '/' + file);
res.stream()
.pipe(fs.createWriteStream('.' + path + '/' + file))
.on('close', function () {
watch(file, path);
})
})
;
})
}
})
;
// watch files
var wFiles = fs.readdirSync('.' + path);
wFiles.forEach(function (file) {
console.log('watching', '.' + path + '/' + file);
watch(file, path);
})
})
/**
* Clone one dpd configuration into another.
*/
program
.command('clone')
.description(' - clone the configuration and files of one instance into another')
.action(function () {
var port = program.port || 2403;
if(!program.storage || !program.destination) throw 'a destination (--dest) and storage (--storage) are required';
dpd.storage(program.storage);
dpd.use('/resources').get(function (err, resources) {
if(!resources) {
json({status: 'none found'});
log('none found');
process.kill(process.pid);
return;
};
if(err) throw err;
var dest = dpd.use('/resources');
dest.storage(program.destination);
dest.post(resources, function (err) {
if(err) throw err;
var remaining = 0;
resources.forEach(function (resource) {
if(resource.type === 'Static') {
dpd.storage(program.storage);
// / is an alias for /index
var collection = resource.path;
if(collection === '/') collection = '/index';
var srcFiles = require('mdoq').require('mdoq-mongodb').use(program.storage).use(collection);
var destFiles = require('mdoq').require('mdoq-mongodb').use(program.destination).use(collection);
dpd.use(resource.path).get({}, function (err, files) {
files.forEach(function (file) {
remaining++;
var id = {_id: file};
srcFiles.get(id, function (err, res) {
if(err) log(err);
if(!err && res) {
var temp = require('fs').createWriteStream('/tmp/' + file);
res.file.stream(true).pipe(temp).on('close', function () {
destFiles.get({}).file(require('fs').createReadStream('/tmp/' + file)).post(function (err) {
remaining--;
if(!remaining) {
json({status: 'done.'});
log('done.');
}
})
})
}
})
})
})
}
})
})
})
})
;
// Parse
program.parse(process.argv);