Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[api doc] Added more command for Apps and Snapshots. Updated code doc…

…umentation
  • Loading branch information...
commit 3ecc03ce6f073b30a557b1b5df7b5a4672ed3b04 1 parent 3258b2a
@indexzero indexzero authored
View
8 lib/jitsu/api/apps.js
@@ -54,7 +54,7 @@ Apps.prototype.create = function (app, callback) {
// Updates the application with `name` with the specified attributes in `attrs`
//
Apps.prototype.update = function (name, attrs, callback) {
- this._request('PUT', ['apps', name], attrs, callback, function (err, res, body) {
+ this._request('PUT', ['apps', name], attrs, callback, function (res, result) {
});
};
@@ -65,8 +65,8 @@ Apps.prototype.update = function (name, attrs, callback) {
// #### @callback {function} Continuation to pass control to when complete
// Destroys the application with `name` for the authenticated user.
//
-Apps.prototype.destory = function (name, callback) {
- this._request('DELETE', ['apps', name], callback, function (err, res, body) {
-
+Apps.prototype.destroy = function (name, callback) {
+ this._request('DELETE', ['apps', jitsu.config.username, name], callback, function (res, result) {
+ callback();
});
};
View
53 lib/jitsu/api/client.js
@@ -6,6 +6,7 @@
*/
var eyes = require('eyes'),
+ fs = require('fs'),
request = require('request'),
jitsu = require('jitsu');
@@ -72,3 +73,55 @@ Client.prototype._request = function (method, uri /* variable arguments */) {
success(response, result);
});
};
+
+//
+// ### function _upload (uri, contentType, file, callback, success)
+// #### @uri {Array} Locator for the Remote Resource
+// #### @contentType {string} Content-Type header to use for the upload.
+// #### @file {string} Path of the local file to upload.
+// #### @success {function} Continuation to call upon successful transactions
+// #### @callback {function} Continuation to call if errors occur.
+// Makes a `POST` request to `this.remoteUri + uri` with the data in `file`
+// as the request body. Short circuits to `callback` if the response
+// code from Nodejitsu matches `jitsu.failCodes`.
+//
+Client.prototype._upload = function (uri, contentType, file, callback, success) {
+ var options, out, self = this,
+ encoded = jitsu.utils.base64.encode(this.options.auth);
+
+ fs.readFile(file, function (err, data) {
+ options = {
+ method: 'POST',
+ uri: self.options.remoteUri + '/' + uri.join('/'),
+ headers: {
+ 'Authorization': 'Basic ' + encoded,
+ 'Content-Type': contentType,
+ 'Content-Length': data.length
+ }
+ };
+
+ out = request(options, function (err, response, body) {
+ if (err) {
+ return callback(err);
+ }
+
+ try {
+ var statusCode = response.statusCode.toString(),
+ result = JSON.parse(body);
+ }
+ catch (ex) {
+ // Ignore Errors
+ }
+
+ if (Object.keys(jitsu.failCodes).indexOf(statusCode) !== -1) {
+ var error = new Error('Nodejitsu Error (' + statusCode + '): ' + jitsu.failCodes[statusCode]);
+ error.result = result;
+ return callback(error);
+ }
+
+ success(response, result);
+ });
+
+ fs.createReadStream(file).pipe(out);
+ });
+};
View
4 lib/jitsu/api/snapshots.js
@@ -44,7 +44,7 @@ Snapshots.prototype.list = function (name, callback) {
// the `*.tgz` package data in `snapshot`.
//
Snapshots.prototype.create = function (name, snapshot, callback) {
- this._request('POST', ['apps', app.name, 'snapshots'], app, callback, function (err, res, body) {
-
+ this._upload(['apps', jitsu.config.username, name, 'snapshots'], 'application/octet-stream', snapshot, callback, function (res, body) {
+ callback(null);
});
};
View
87 lib/jitsu/commands/apps.js
@@ -10,8 +10,17 @@ var winston = require('winston'),
var apps = exports;
+//
+// ### function list (callback)
+// #### @callback {function} Continuation to pass control to when complete.
+// Lists the applications for the authenticated user.
+//
apps.list = function (callback) {
jitsu.apps.list(function (err, apps) {
+ if (err) {
+ return callback(err);
+ }
+
var rows = [['name', 'state', 'subdomain', 'start', 'latest']],
colors = ['underline', 'yellow', 'green', 'grey', 'red'];
@@ -26,9 +35,17 @@ apps.list = function (callback) {
});
jitsu.log.logRows('data', rows, colors);
+ callback();
});
};
+//
+// ### 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 `name` if supplied and falling back to `package.name`.
+//
apps.create = function (name, callback) {
jitsu.utils.readPackage(process.cwd(), function (err, pkg) {
if (!callback) {
@@ -37,21 +54,34 @@ apps.create = function (name, callback) {
}
pkg.name = name || pkg.name;
- //
- // TODO (indexzero): Configure this default value in nodejitsu APIs
- //
- pkg.state = 'stopped';
- winston.info('Validating package.json for ' + pkg.name.magenta);
- jitsu.prompt.addProperties(pkg, ['subdomain'], function (updated) {
- winston.info('Creating app ' + pkg.name.magenta);
- jitsu.apps.create(updated, function (err, res, result) {
- winston.silly('Done creating app ' + pkg.name.magenta);
- return err ? callback(err) : callback();
+ jitsu.apps.list(function (err, apps) {
+ var existing = apps.filter(function (a) { return a.name === pkg.name });
+ if (existing.length > 0) {
+ return winston.warn('Cannot create duplicate application ' + pkg.name.magenta);
+ }
+
+ //
+ // TODO (indexzero): Configure this default value in nodejitsu APIs
+ //
+ pkg.state = 'stopped';
+ winston.info('Validating package.json for ' + pkg.name.magenta);
+ jitsu.prompt.addProperties(pkg, ['subdomain'], function (updated) {
+ winston.info('Creating app ' + pkg.name.magenta);
+ jitsu.apps.create(updated, function (err, res, result) {
+ winston.silly('Done creating app ' + pkg.name.magenta);
+ return err ? callback(err) : callback();
+ });
});
});
});
};
+//
+// ### 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;
@@ -60,14 +90,51 @@ apps.update = function (name, callback) {
};
+//
+// ### 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 `name`. If no name is supplied
+// this will destroy the application in the current directory.
+//
apps.destroy = function (name, callback) {
+ if (!callback) {
+ callback = name;
+ return jitsu.utils.readPackage(process.cwd(), function (err, package) {
+ name = package.name;
+ executeDestroy();
+ });
+ }
+
+ 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();
+ });
+ }
+ executeDestroy();
};
+//
+// ### 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 `name`. If no name is supplied
+// this will start the application in the current directory.
+//
apps.start = function (name, callback) {
};
+//
+// ### 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 `name`. If no name is supplied
+// this will stop the application in the current directory.
+//
apps.stop = function (name, callback) {
};
View
26 lib/jitsu/commands/config.js
@@ -9,13 +9,26 @@ var jitsu = require('jitsu'),
winston = require('winston');
var config = exports,
- noDelete = ['root', 'remoteUri', 'userconfig', 'auth'];
+ noDelete = ['root', 'remoteUri', 'userconfig', 'auth', 'tmproot', 'tar', 'gzipbin'];
+//
+// ### function set (key, value, callback)
+// #### @key {string} Key to set in jitsu config.
+// #### @value {string} Value to set the key to.
+// #### @callback {function} Continuation to pass control to when complete
+// Sets the specified `key` in jitsu config to `value`.
+//
config.set = function (key, value, callback) {
jitsu.config.settings[key] = value;
jitsu.config.save(callback);
};
+//
+// ### function get (key, callback)
+// #### @key {string} Key to get in jitsu config.
+// #### @callback {function} Continuation to pass control to when complete
+// Gets the specified `key` in jitsu config.
+//
config.get = function (key, callback) {
if (!jitsu.config.settings[key]) {
return winston.error('No configuration value for ' + key.yellow);
@@ -25,6 +38,12 @@ config.get = function (key, callback) {
callback();
};
+//
+// ### function delete (key, callback)
+// #### @key {string} Key to delete, in jitsu config.
+// #### @callback {function} Continuation to pass control to when complete
+// Deletes the specified `key` in jitsu config.
+//
config.delete = function (key, callback) {
if (!jitsu.config.settings[key]) {
return winston.error('No configuration value for ' + key.yellow);
@@ -39,6 +58,11 @@ config.delete = function (key, callback) {
jitsu.config.save(callback);
};
+//
+// ### function list (callback)
+// #### @callback {function} Continuation to pass control to when complete
+// Lists all the key-value pairs in jitsu config.
+//
config.list = function (callback) {
function listObject (obj, prefix) {
prefix = prefix || '';
View
47 lib/jitsu/commands/snapshots.js
@@ -5,10 +5,18 @@
*
*/
-var jitsu = require('jitsu');
+var winston = require('winston'),
+ jitsu = require('jitsu');
var snapshots = exports;
+//
+// ### function list (name, callback)
+// #### @name {string} **optional** Name of the application to create
+// #### @callback {function} Continuation to pass control to when complete.
+// Lists the snapshots for the application belonging for the authenticated user.
+// If `name` is not supplied the value for name in `package.name` will be used.
+//
snapshots.list = function (name, callback) {
if (!callback) {
callback = name;
@@ -39,10 +47,41 @@ snapshots.list = function (name, callback) {
executeList();
};
-snapshots.create = function (name, callback) {
-
+//
+// ### function create (name, callback)
+// #### @name {string} **optional** Name of the application to create
+// #### @callback {function} Continuation to pass control to when complete.
+// Creates a snapshots for the application belonging for the authenticated user
+// using the data in the current directory. If `name` is not supplied the
+// value for name in `package.name` will be used.
+//
+snapshots.create = function (name, callback) {
+ //
+ // TODO (indexzero): Ensure `snapshot create ../../` works
+ //
+ jitsu.utils.createPackage(process.cwd(), function (err, pkg, filename) {
+ if (!callback) {
+ callback = name;
+ name = null;
+ }
+
+ name = name || pkg.name;
+ winston.info('Creating snapshot for ' + name.magenta);
+ winston.silly('Filename: ' + filename);
+ jitsu.snapshots.create(name, filename, function (err, snapshots) {
+ winston.info('Done creating snapshot ' + name.magenta);
+ return err ? callback(err) : callback();
+ });
+ });
};
-snapshots.destroy = function (name, callback) {
+//
+// ### function destroy (count, callback)
+// #### @count {string} **optional** Number of snapshots to destroy
+// #### @callback {function} Continuation to pass control to when complete.
+// Destroys the specified number of snapshots for the application in the current
+// directory. If `count` is not supplied one snapshot will be destroyed.
+//
+snapshots.destroy = function (count, callback) {
};
View
5 lib/jitsu/config.js
@@ -12,7 +12,10 @@ var path = require('path'),
var config = exports, settings = config.settings = {
root: process.env.HOME,
remoteUri: 'http://localhost',
- userconfig: '.jitsuconf'
+ userconfig: '.jitsuconf',
+ tmproot: '/tmp',
+ tar: 'tar',
+ gzipbin: 'gzip'
};
//
View
8 lib/jitsu/prompt.js
@@ -132,6 +132,14 @@ prompt.getInput = function (msg, validator, callback) {
return prompt;
};
+//
+// ### function addProperties (obj, properties, callback)
+// #### @obj {Object} Object to add properties to
+// #### @properties {Array} List of properties to get values for
+// #### @callback {function} Continuation to pass control to when complete.
+// Prompts the user for values each of the `properties` if `obj` does not already
+// have a value for the property. Responds with the modified object.
+//
prompt.addProperties = function (obj, properties, callback) {
properties = properties.filter(function (prop) {
return typeof obj[prop] === 'undefined';
View
68 lib/jitsu/utils/index.js
@@ -5,18 +5,33 @@
*
*/
-var fs = require('fs'),
+var jitsu = require('jitsu'),
+ util = require('util'),
+ spawn = require('child_process').spawn,
+ fs = require('fs'),
path = require('path');
var utils = exports;
utils.base64 = require('./base64');
+//
+// ### function snapshotTime (name)
+// #### @name {string} Filename for the snapshot
+// Returns a formatted date string for the unix time
+// in the snapshot filename.
+//
utils.snapshotTime = function (name) {
var time = name.match(/[\w|\-]+-[\w|\-]+-(\d+)/)[1];
return utils.formatTime(new Date(parseInt(time)));
};
+//
+// ### function formatTime (obj)
+// #### @obj {Date} Date to format
+// Returns a formatted date string for `obj` in the format
+// YYYY/MM/DD HH:MM:SS
+//
utils.formatTime = function (obj) {
var date = [obj.getFullYear(), obj.getMonth(), obj.getDate()].join('/'),
time = [obj.getHours(), obj.getMinutes(), obj.getSeconds()].join(':');
@@ -24,6 +39,12 @@ utils.formatTime = function (obj) {
return [date, time].join(' ');
};
+//
+// ### function readPackage (dir, callback)
+// #### @dir {string} Directory to read the package.json from
+// #### @callback {function} Continuation to pass control to when complete
+// Attempts to read the package.json file out of the specified directory.
+//
utils.readPackage = function (dir, callback) {
var file = path.join(dir, 'package.json');
@@ -39,4 +60,49 @@ utils.readPackage = function (dir, callback) {
callback(ex);
}
});
+};
+
+//
+// ### function createPackage (dir, callback)
+// #### @dir {string} Directory to create the package *.tgz file from
+// #### @callback {function} Continuation to pass control to when complete
+// Creates a *.tgz package file from the specified directory `dir`.
+//
+utils.createPackage = function (dir, callback) {
+ utils.readPackage(dir, function (err, pkg) {
+ if (err) {
+ return callback(err);
+ }
+
+ if (dir.slice(-1) === '/') dir = dir.slice(0, -1);
+ var parent = path.dirname(dir),
+ base = path.basename(dir),
+ tarball = path.join(jitsu.config.settings.tmproot, [jitsu.config.username, pkg.name, Date.now()].join('-') + '.tgz'),
+ target = fs.createWriteStream(tarball),
+ tarargs = ['-cvf', '-', '--exclude', '.git', '-C', parent, base];
+
+ //
+ // TODO (indexzero) Support for `.jitsuignore` files and support for package.json files
+ //
+ var tar = spawn(jitsu.config.settings.tar, tarargs),
+ gzip = spawn(jitsu.config.settings.gzipbin, ["--stdout"]),
+ errState;
+
+ //
+ // TODO (indexzero) Make this piping more robust
+ //
+ util.pump(tar.stdout, gzip.stdin);
+ util.pump(gzip.stdout, target);
+
+ target.on("close", function (err, ok) {
+ if (errState) {
+ return
+ }
+ else if (err) {
+ return callback(errState = err)
+ }
+
+ callback(null, pkg, tarball);
+ });
+ });
};
Please sign in to comment.
Something went wrong with that request. Please try again.