apps.js | |
---|---|
/*
* apps.js: Commands related to app resources
*
* (C) 2010, Nodejitsu Inc.
*
*/
var eyes = require('eyes'),
winston = require('winston'),
analyzer = require('require-analyzer'),
jitsu = require('jitsu');
var apps = exports;
apps.usage = [
'`jitsu apps *` commands allow you to work with your',
'Applications on Nodejitsu. Valid commands are:',
'',
'jitsu apps create',
'jitsu apps list',
'jitsu apps deploy',
'jitsu apps view [<name>]',
'jitsu apps update [<name>]',
'jitsu apps destroy [<name>]',
'jitsu apps start [<name>]',
'jitsu apps restart [<name>]',
'jitsu apps stop [<name>]',
'',
'For commands that take a <name> parameter, if no parameter',
'is supplied, jitsu will attempt to read the package.json',
'from the current directory.'
]; | |
function deploy (callback)@callback {function} Continuation to respond to when complete.Deploys an application through the following steps: 1. Creates the application (if necessary) 2. Creates or validates the package.json 3. Packages and creates a new snapshot 4. Stops the application (if neccessary) 5. Starts the application | apps.deploy = function (callback) {
var dir = process.cwd(), pkg;
function startApp (err, existing) {
if (err) {
winston.error('Error creating snapshot for app ' + pkg.name.magenta);
winston.error(err.message);
return callback(new Error(), true);
}
if (existing.state === 'started') {
apps.stop(existing.name, function (err) {
return err ? callback(err) : apps.start(existing.name, callback);
});
}
else {
apps.start(existing.name, callback);
}
}
function activateSnapshot (existing, snapshot) {
winston.info('Activating snapshot ' + snapshot.grey + ' for ' + existing.name.magenta);
jitsu.snapshots.activate(existing.name, snapshot, function (err) {
winston.silly('Done activating snapshot ' + snapshot.grey);
startApp(err, existing);
});
}
function updateApp (existing, snapshot) {
winston.info('Updating application ' + existing.name.magenta);
jitsu.apps.update(existing.name, pkg, function (err) {
if (err) {
return callback(err);
}
activateSnapshot(existing, snapshot);
});
}
function updateSnapshot (err, existing, firstSnapshot) {
if (err) {
return callback(err, true, true);
}
jitsu.package.updateTarball(null, pkg, existing, firstSnapshot, function (err, snapshot) {
if (err) {
return callback(err, snapshot);
}
updateApp(existing, snapshot);
});
}
function checkApp (err, local) {
if (err) {
winston.error(err);
return callback(new Error(), true);
}
pkg = local;
winston.silly('Checking if application ' + local.name.magenta + ' exists.');
jitsu.apps.view(local.name, function (err, app) {
if (err) {
winston.warn('No application exists for ' + local.name.magenta);
|
If there is a before filter we should run before creating the app do so, then create the application. | return apps.create(local.name, function (err, existing) {
updateSnapshot(err, existing, true);
});
}
app = !app ? {} : jitsu.utils.formatApp(app, ['snapshots', 'active', 'user', 'state']);
var pkg = analyzer.merge({}, local, app);
jitsu.package.validate(pkg, dir, updateSnapshot);
});
}
jitsu.package.read(dir, function (err, local) {
return err ? jitsu.package.get(dir, checkApp) : checkApp(null, local);
});
};
apps.deploy.usage = [
'',
'Deploys an application using the following steps:'.cyan.underline,
'',
' 1. Creates the application (if necessary)',
' 2. Creates or validates the package.json',
' 3. Packages and creates a new snapshot',
' 4. Stops the application (if neccessary)',
' 5. Starts the application',
'',
'jitsu deploy',
'jitsu apps deploy'
]; |
function list (callback)@name {string} optional Name of the application to create@callback {function} Continuation to pass control to when complete.Creates an application for the package.json in the current directory
using | apps.create = function (name, callback) {
jitsu.package.get(process.cwd(), function (err, pkg) {
if (!callback) {
callback = name;
name = null;
}
if (err) {
winston.error(err);
return callback(new Error(), true);
}
pkg.name = name || pkg.name;
jitsu.apps.list(function (err, apps) {
var username = jitsu.config.get('username');
var existing = apps.filter(function (a) {
return a.name === pkg.name && a.user === username;
});
if (existing.length > 0) {
return callback(new Error('Cannot create duplicate application ' + pkg.name.magenta), true, true);
}
|
TODO (indexzero): Configure this default value in nodejitsu APIs | pkg.state = 'stopped';
winston.info('Checking app availability ' + pkg.name.magenta);
jitsu.apps.available(pkg, function (err, result) {
if (!result.available) {
winston.error('Error creating ' + pkg.name.magenta);
winston.error(result.message);
return callback(new Error());
}
winston.info('Creating app ' + pkg.name.magenta);
jitsu.apps.create(pkg, function (err, res, result) {
winston.silly('Done creating app ' + pkg.name.magenta);
return err ? callback(err) : callback(null, pkg);
});
});
});
});
}; |
Usage for | apps.create.usage = [
'Creates an application using the package.json file in the',
'current directory, if <name> is supplied then this is used',
'instead of the `name` property in the package.json file.',
'',
'jitsu create',
'jitsu apps create',
'jitsu apps create <name>'
]; |
function list (callback)@callback {function} Continuation to pass control to when complete.Lists the applications for the authenticated user. | apps.list = function (callback) {
winston.info('Listing apps');
jitsu.apps.list(function (err, apps) {
if (err) {
return callback(err);
}
if (!apps || apps.length === 0) {
winston.warn('No applications exist.');
winston.help('Try creating one with ' + 'jitsu apps create'.magenta);
return callback();
}
var rows = [['name', 'state', 'subdomain', 'start', 'latest']],
colors = ['underline', 'underline', 'underline', 'underline', 'underline'];
apps.forEach(function (app) {
rows.push([
app.name,
app.state || 'stopped',
app.subdomain,
app.scripts.start || '---',
app.snapshots && app.snapshots.length > 0 ? app.snapshots[0].filename : '---'
]);
});
jitsu.log.putRows('data', rows, colors);
callback();
});
}; |
Usage for | apps.list.usage = [
'Lists all of the applications for the current user',
'',
'jitsu list',
'jitsu apps list'
]; |
function view (name, callback)@name {string} optional Name of the application to view@callback {function} Continuation to pass control to when complete.Views the application with the specfied | apps.view = function (name, callback) {
function executeView() {
jitsu.apps.view(name, function (err, app) {
if (err) {
return callback(err);
}
app = jitsu.utils.formatApp(app);
jitsu.log.putObject(app);
callback(null, app);
});
}
if (!callback) {
callback = name;
return jitsu.package.tryRead(process.cwd(), callback, function (pkg) {
name = pkg.name;
executeView();
});
}
executeView();
}; |
Usage for | apps.view.usage = [
'Lists the information for the application in the current',
'directory. If <name> is supplied then that application',
'is listed instead.',
'',
'jitsu apps view',
'jitsu apps view <name>'
]; |
function list (callback)@name {string} optional Name of the application to create@callback {function} Continuation to pass control to when complete.Lists the applications for the authenticated user. | apps.update = function (name, callback) {
if (!callback) {
callback = name;
name = null;
}
winston.silly('Reading package.json in ' + process.cwd());
jitsu.package.tryRead(process.cwd(), callback, function (pkg) {
name = name || pkg.name;
jitsu.apps.view(name, function (err, app) {
if (err) {
return callback(err);
}
var diff = jitsu.utils.objectDiff(app, pkg);
if (!diff) {
winston.warn('No changes found to your package.json for ' + name.magenta);
return callback();
}
winston.info('Updating application ' + name.magenta + ' with:');
jitsu.log.putObject(diff);
jitsu.apps.update(name, diff, callback);
});
});
}; |
Usage for | apps.update.usage = [
'Updates the application in the current directory',
'with the information in the package.json file. If',
'<name> is supplied the application with <name> is updated.',
'',
'jitsu apps update',
'jitsu apps update <name>'
]; |
function destroy (callback)@name {string} optional Name of the application to destroy.@callback {function} Continuation to pass control to when complete.Destroys the application specified by | apps.destroy = function (name, callback) {
function executeDestroy() {
winston.info('Destroying app ' + name.magenta);
jitsu.apps.destroy(name, function (err) {
winston.silly('Done destroying app ' + name.magenta);
return err ? callback(err) : callback();
});
}
if (!callback) {
callback = name;
return jitsu.package.tryRead(process.cwd(), callback, function (pkg) {
name = pkg.name;
executeDestroy();
});
}
executeDestroy();
}; |
Usage for | apps.destroy.usage = [
'Destroys the application in the current directory. If',
'<name> is supplied then that application is destroyed instead',
'',
'jitsu apps destroy',
'jitsu apps destroy <name>'
]; |
function start (callback)@name {string} optional Name of the application to start.@callback {function} Continuation to pass control to when complete.Starts the application specified by | apps.start = function (name, callback) {
function executeStart() {
winston.info('Starting app ' + name.magenta);
jitsu.apps.start(name, function (err) {
if (err) {
return callback(err, true);
}
jitsu.apps.view(name, function (err, app) {
if (err) {
return callback(err);
}
winston.info('App ' + name.magenta + ' is now started')
winston.info(('http://' + app.subdomain + '.nodejitsu.com').magenta + ' on Port ' + '80'.magenta);
callback();
});
});
}
if (!callback) {
callback = name;
return jitsu.package.tryRead(process.cwd(), callback, function (pkg) {
name = pkg.name;
executeStart();
});
}
executeStart();
}; |
Usage for | apps.start.usage = [
'Starts the application in the current directory. If <name>',
'is supplied then that application is started instead.',
'',
'jitsu apps start',
'jitsu apps start <name>'
]; |
function restart (name, callback)@name {string} optional Name of the application to restart.@callback {function} Continuation to pass control to when complete.Restarts the application specified by | apps.restart = function (name, callback) {
function executeRestart() {
winston.info('Restarting app ' + name.magenta);
jitsu.apps.restart(name, function (err) {
if (err) {
return callback(err);
}
winston.info('App ' + name.magenta + ' has been restarted');
callback();
});
}
if (!callback) {
callback = name;
return jitsu.package.tryRead(process.cwd(), callback, function (pkg) {
name = pkg.name;
executeRestart();
});
}
executeRestart();
}; |
Usage for | apps.restart.usage = [
'Restarts the application in the current directory. If <name>',
'is supplied then that application is restarted instead.',
'',
'jitsu apps restart',
'jitsu apps restart <name>'
]; |
function stop (callback)@name {string} optional Name of the application to stop.@callback {function} Continuation to pass control to when complete.Stops the application specified by | apps.stop = function (name, callback) {
function executeStop() {
winston.info('Stopping app ' + name.magenta);
jitsu.apps.stop(name, function (err) {
if (err) {
return callback(err);
}
winston.info('App ' + name.magenta + ' is now stopped');
callback();
});
}
if (!callback) {
callback = name;
return jitsu.package.tryRead(process.cwd(), callback, function (pkg) {
name = pkg.name;
executeStop();
});
}
executeStop();
}; |
Usage for | apps.stop.usage = [
'Stops the application in the current directory. If <name>',
'is supplied then that application is stopped instead.',
'',
'jitsu apps stop',
'jitsu apps stop <name>'
];
|