Permalink
Browse files

[merge] Upgrade branch into master

  • Loading branch information...
1 parent 255f0e6 commit 6f8cf7271d50e3f9db12301e6b412544fd4e3264 @alejandro alejandro committed Apr 6, 2012
View
2 README.md
@@ -29,7 +29,7 @@ http://youtu.be/jwsP1Ejv-_w
## Installing Nodester on Amazon EC2, Rackspace, GoGrid, or your own datacenter services
-Please see install.md for setup instructions (https://github.com/nodester/nodester/blob/master/install.md)
+Please [read the wiki](https://github.com/nodester/nodester/wiki/Install-nodester) for setup instructions
## Testing Locally
View
484 app.js
@@ -1,76 +1,84 @@
#!/usr/bin/env node
/*
-
-Nodester opensource Node.js hosting service
-
-Written by: @ChrisMatthieu & @DanBUK
-http://nodester.com
-
+ * Nodester opensource Node.js hosting service
+ * Written by: @ChrisMatthieu & @DanBUK
+ * Mainteiner: Alejandro Morales (@_alejandromg)
+ * http://nodester.com
+ * http://github.com/nodester
*/
-require('coffee-script');
-
-var express = require('express'),
- url = require('url'),
- sys = require('sys'),
- path = require('path'),
- config = require('./config'),
- middle = require('./lib/middle'),
- stats = require('./lib/stats');
-
-var daemon = require('daemon');
-// daemon.setreuid(config.opt.userid);
-var myapp = express.createServer();
-
-myapp.configure(function () {
- myapp.use(express.bodyParser());
- myapp.use(express.static(config.opt.public_html_dir));
- myapp.use(express.errorHandler({
+
+var express = require('express')
+ , url = require('url')
+ , sys = require('util')
+ , path = require('path')
+ , Logger = require('bunyan')
+ , log = process.log = new Logger({name: "nodester"})
+ , config = require('./config')
+ , middle = require('./lib/middle')
+ , stats = require('./lib/stats')
+ ;
+
+var __app__ = express.createServer()
+ , app = __app__
+ ;
+
+app.configure(function () {
+ app.use(express.bodyParser());
+ app.use(express.logger('dev'))
+ app.use(express.static(config.opt.public_html_dir));
+ app.use(express.errorHandler({
showStack: true,
dumpExceptions: true
}));
});
-
-// Error handler
-myapp.error(function (err, req, res, next) {
- if (err instanceof NotFound) {
- res.sendfile(__dirname + '/public/404.html');
- } else {
- res.sendfile(__dirname + '/public/500.html');
- }
-});
-
-
/*
- * dev dashboard emitter
+ * status emitter
*/
+
var bolt = require('bolt');
-var mesh = new bolt.Node({
+
+var dash = new bolt.Node({
delimiter : '::',
host : config.opt.redis.host,
port : config.opt.redis.port,
user : config.opt.redis.user,
auth : config.opt.redis.auth,
silent : true
});
-mesh.start();
-myapp.all('*',function(req,res,next){
+dash.start();
+
+/*
+ * Error handler
+ */
+
+app.error(function (err, req, res, next) {
+ if (err instanceof NotFound) {
+ res.sendfile(__dirname + '/public/404.html')
+ } else {
+ log.warn(err)
+ dash.emit('nodester::500',{msg:err.message,stack:err.stack.toString()})
+ res.sendfile(__dirname + '/public/500.html')
+ }
+});
+
+app.all('*',function(req,res,next){
if (!path.extname(req.url)){
var ip = req.connection.remoteAddress || req.socket.remoteAddress;
if (req.headers["x-real-ip"]) ip =req.headers["x-real-ip"];
var toEmit = {
ip : ip,
- url : req.url ,
+ url : req.url,
time : new Date,
method : req.method,
ua : req.headers['user-agent'] || 'nodester',
host : req.headers.host
}
- mesh.emit('nodester::incomingRequest', toEmit);
+ dash.emit('nodester::incomingRequest', toEmit)
}
- next();
+ next()
})
function getStats(){
@@ -79,186 +87,291 @@ function getStats(){
// ignore childprocess which can cause high latency
if (stat != 'getDiskUsage' && stat != 'getProcesses'){
statistics[stat] = stats[stat]()
- } /* else {
- stats[stat](function(error,resp){
- if (!error)
- statistics[stat] = resp;
- else
- statistics[stat] = '0'
- });
- }*/
+ }
}
return statistics;
}
+/*
+ * Ping every 3 seconds
+*/
setInterval(function(){
- mesh.emit('nodester::ping',{date:new Date})
-},3000);
+ dash.emit('nodester::ping',{date:new Date})
+},3000)
-setInterval(function(){
- mesh.emit('nodester::stats',getStats());
-},6500);
+/*
+ * emit stats every 5 seconds
+*/
+setInterval(function(){
+ dash.emit('nodester::stats',getStats())
+}, 5000)
process.on('uncaughtException', function (err) {
- mesh.emit('nodester::uE', err);
- console.log(err.stack);
-});
-
-
+ dash.emit('nodester::uE',{ msg:err.message,stack:err.stack.toString()})
+ log.fatal(err.stack)
+})
/* Routes */
-// Homepage
-myapp.get('/', function (req, res, next) {
- res.sendfile(__dirname +'/public/index.html');
+/*
+ * Homepage Showcase
+ *
+ */
+app.get('/', function (req, res, next) {
+ res.sendfile(__dirname +'/public/index.html')
});
-
-myapp.get('/api', function (req, res, next) {
- res.redirect('/api.html');
+app.get('/api', function (req, res, next) {
+ res.sendfile(__dirname +'/public/api.html')
});
-
-myapp.get('/admin', function (req, res, next) {
+app.get('/help', function (req, res, next) {
+ res.sendfile(__dirname +'/public/help.html')
+});
+app.get('/about', function (req, res, next) {
+ res.sendfile(__dirname +'/public/about.html')
+});
+app.get('/admin', function (req, res, next) {
res.redirect('http://admin.nodester.com');
});
-
-myapp.get('/irc', function (req, res, next) {
+app.get('/irc', function (req, res, next) {
res.redirect('http://irc.nodester.com');
});
-
-myapp.get('/monitor', function (req, res, next) {
- res.redirect('http://site.nodester.com');
+app.get('/status', function (req, res, next) {
+ res.redirect('http://status.nodester.com');
});
-/* Status API */
-// http://localhost:4001/status
-// curl http://localhost:4001/status
+/*
+ * shorthands
+*/
+var auth = middle.authenticate
+ , authApp = middle.authenticate_app
+ , authAdmin = middle.authenticate_admin
+ , deprecated = middle.deprecated
+ ;
+
+/*
+ * Status endPoint
+ * @Public: true
+ * @HTTP method: http://api.host.com/status
+ * @raw: curl http://api.host.com/status
+ * @cli: nodester status
+ */
var status = require('./lib/status');
-myapp.get('/status', status.get);
-// New coupon request
-// curl -X POST -d "email=dan@nodester.com" http://localhost:4001/coupon
-var coupon = require('./lib/coupon');
-myapp.post('/coupon', coupon.post);
+app.get('/status', status.get);
-// curl http://localhost:4001/unsent
-myapp.get('/unsent', coupon.unsent);
+/*
+ * New coupon request
+ * @Public: true
+ * @raw:
+ * # send coupon
+ * curl -X POST -d "email=dan@nodester.com" http://localhost:4001/coupon
+ *: curl http://localhost:4001/unsent
+ * @cli: nodester coupon
+ */
+var coupon = require('./lib/coupon');
+app.post('/coupon', coupon.post);
+app.get('/unsent', coupon.unsent);
+
+/*
+ * User actions
+ */
-// New user account registration
-// curl -X POST -d "user=testuser&password=123&email=chris@nodefu.com&coupon=hiyah" http://localhost:4001/user
-// curl -X POST -d "user=me&password=123&coupon=hiyah" http://localhost:4001/user
var user = require('./lib/user');
-myapp.post('/user', user.post);
-// localhost requires basic auth to access this section
-// Edit your user account
-// curl -X PUT -u "testuser:123" -d "password=test&rsakey=1234567" http://localhost:4001/user
-myapp.put('/user', middle.authenticate, user.put);
+/*
+ * New user account registration
+ * @Public: true with params
+ * @params: user,password,email,coupon
+ * @raw: curl -X POST -d "user=testuser&password=123&email=chris@nodefu.com&coupon=hiyah" http://localhost:4001/user
+ * curl -X POST -d "user=me&password=123&coupon=hiyah" http://localhost:4001/user
+ * @cli: nodester user register <coupon-code>
+ */
+
+app.post('/user', user.post);
+
+
+/*
+ * Edit your user account
+ * @Public: false, only with authentication
+ * @raw: curl -X PUT -u "testuser:123" -d "password=test&rsakey=1234567" http://localhost:4001/user
+ * @cli: nodester user
+ */
+
+app.put('/user', auth, user.put);
-// Delete your user account
-// curl -X DELETE -u "testuser:123" http://localhost:4001/user
-myapp.del('/user', middle.authenticate, user.delete);
-// All Applications info
-// http://chris:123@localhost:4001/apps
-// curl -u "testuser:123" http://localhost:4001/apps
+/*
+ * Delete your user account
+ * @Public: false, only with authentication
+ * @raw: curl -X DELETE -u "testuser:123" http://localhost:4001/user
+ * @cli: not available,security issues
+*/
+app.del('/user', auth, user.delete);
+
+/*
+ * Apps related info
+ */
var apps = require('./lib/apps');
-myapp.get('/apps', middle.authenticate, apps.get);
-
-
-var app = require('./lib/app');
-
-// Application info
-// http://chris:123@localhost:4001/apps/<appname>
-// curl -u "testuser:123" http://localhost:4001/apps/<appname>
-myapp.get('/apps/:appname', middle.authenticate, middle.authenticate_app, app.get);
-myapp.get('/app/:appname', middle.deprecated, middle.authenticate, middle.authenticate_app, app.get); // deprecated
-
-// Create node app
-// curl -X POST -u "testuser:123" -d "appname=test&start=hello.js" http://localhost:4001/apps
-myapp.post('/apps/:appname', middle.authenticate, app.post);
-myapp.post('/apps', middle.authenticate, app.post);
-myapp.post('/app', middle.deprecated, middle.authenticate, app.post); // deprecated
-
-// App backend restart handler
-myapp.get('/app_restart', app.app_restart);
-myapp.get('/app_start', app.app_start);
-myapp.get('/app_stop', app.app_stop);
-
-// Update node app
-// start=hello.js - To update the initial run script
-// running=true - To Start the app
-// running=false - To Stop the app
-// curl -X PUT -u "testuser:123" -d "start=hello.js" http://localhost:4001/apps/test
-// curl -X PUT -u "testuser:123" -d "running=true" http://localhost:4001/apps/test
-// curl -X PUT -u "testuser:123" -d "running=false" http://localhost:4001/apps/test
-// curl -X PUT -u "testuser:123" -d "running=restart" http://localhost:4001/apps/test
-// TODO - Fix this function, it's not doing callbacking properly so will return JSON in the wrong state!
-myapp.put('/apps/:appname', middle.authenticate, middle.authenticate_app, app.put);
-myapp.put('/app', middle.deprecated, middle.authenticate, middle.authenticate_app, app.put); // deprecated
-myapp.put('/app/audit', middle.authenticate_admin,app.audit);
-myapp.put('/app/restart/:appname', middle.authenticate_admin,app.restartByName);
-// Delete your nodejs app
-// curl -X DELETE -u "testuser:123" -d http://localhost:4001/apps/test
-myapp.del('/apps/:appname', middle.authenticate, middle.authenticate_app, app.delete);
-myapp.del('/app/:appname', middle.deprecated, middle.authenticate, middle.authenticate_app, app.delete); // deprecated
-
-myapp.del('/gitreset/:appname', middle.authenticate, middle.authenticate_app, app.gitreset);
-
-// curl -u "testuser:123" -d "appname=test" http://localhost:4001/applogs
-myapp.get('/applogs/:appname', middle.authenticate, middle.authenticate_app, app.logs);
-
-// Retrieve information about or update a node app's ENV variables
-// This fulfills all four RESTful verbs.
-// GET will retrieve the list of all keys.
-// PUT will either create or update.
-// DELETE will delete the key if it exists.
-// curl -u GET -u "testuser:123" -d "appname=test" http://localhost:4001/env
-// curl -u PUT -u "testuser:123" -d "appname=test&key=NODE_ENV&value=production" http://localhost:4001/env
-// curl -u DELETE -u "testuser:123" -d "appname=test&key=NODE_ENV" http://localhost:4001/env
-
-// Get info about available versions.
-// curl -XGET http://localhost:4001/env/version
-myapp.get('/env/version', app.env_version);
-// Get info about a specific version and see if it's installed
-// without need of basic auth
-// curl -XGET http://localhost:4001/env/:version
-myapp.get('/env/version/:version', app.check_env_version);
-myapp.get('/env/:appname', middle.authenticate, middle.authenticate_app, app.env_get);
-myapp.put('/env', middle.authenticate, middle.authenticate_app, app.env_put);
-myapp.del('/env/:appname/:key', middle.authenticate, middle.authenticate_app, app.env_delete);
-
-// APP NPM Handlers
+/*
+ * All Applications info
+ * @HTTP: http://chris:123@localhost:4001/apps
+ * @raw: curl -u "testuser:123" http://localhost:4001/apps
+ * @cli: nodester apps
+ */
+app.get('/apps', auth, apps.get);
+
+/*
+ * App actions
+ * @Public: false
+ */
+var _app_ = require('./lib/app')
+
+
+/*
+ * Application info
+ * @HTTP: http://chris:123@localhost:4001/apps/<appname>
+ * @raw: curl -u "testuser:123" http://localhost:4001/apps/<appname>
+ * @cli: nodester app info <appname>
+ */
+app.get('/apps/:appname', auth, authApp, _app_.get);
+app.get('/app/:appname', deprecated, auth, authApp, _app_.get); // deprecated
+
+/*
+ * Create node app
+ * @raw: curl -X POST -u "testuser:123" -d "appname=test&start=hello.js" http://localhost:4001/apps
+ * @cli: nodester app create <appname> <initfile.js>
+*/
+
+app.post('/apps/:appname', auth, _app_.post);
+app.post('/apps', auth, _app_.post);
+app.post('/app', deprecated, auth, _app_.post);
+
+/*
+ * App backend restart|start|stop handler
+ * @Public : true
+ * @HTTP : http://api.test.com/app_restart
+ * @cli: nodester app restart|start|stop <appname>
+ */
+app.get('/app_restart', _app_.app_restart);
+app.get('/app_start', _app_.app_start);
+app.get('/app_stop', _app_.app_stop);
+
+/*
+ * Update node app
+ * @Public false only with auth
+ * @params start=initfile.js
+ * @params running=true|false (stop,start)
+ * Raw output:
+ * curl -X PUT -u "testuser:123" -d "start=hello.js" http://localhost:4001/apps/test
+ * curl -X PUT -u "testuser:123" -d "running=true" http://localhost:4001/apps/test
+ * curl -X PUT -u "testuser:123" -d "running=false" http://localhost:4001/apps/test
+ * curl -X PUT -u "testuser:123" -d "running=restart" http://localhost:4001/apps/test
+ * TODO - Fix this function, it's not doing callbacking properly so will return JSON in the wrong state!
+*/
+
+app.put('/apps/:appname', auth, authApp, _app_.put);
+app.put('/app', deprecated, auth,authApp, _app_.put); // deprecated
+
+/*
+ * Admin tasks
+ */
+app.put('/app/audit', authAdmin,_app_.audit);
+app.put('/app/restart/:appname', authAdmin, _app_.restartByName);
+
+/*
+ * Delete your nodejs app
+ * @Public : false (with auth onlye)
+ * @raw : curl -X DELETE -u "testuser:123" -d http://localhost:4001/apps/test
+ */
+app.del('/apps/:appname', auth, authApp, _app_.delete);
+app.del('/app/:appname',deprecated, auth, authApp, _app_.delete); // deprecated
+app.del('/gitreset/:appname', auth, authApp, _app_.gitreset);
+
+/*
+ * Logs
+ * @Public: false
+ * @raw: curl -u "testuser:123" -d "appname=test" http://localhost:4001/applogs
+ */
+app.get('/applogs/:appname', auth, authApp, _app_.logs);
+
+/*
+ * Retrieve information about or update a node app's ENV variables
+ * This fulfills all four RESTful verbs.
+ * @method: GET will retrieve the list of all keys.
+ * @method: PUT will either create or update.
+ * @method: DELETE will delete the key if it exists.
+ * Raw output:
+ * curl -u GET -u "testuser:123" -d "appname=test" http://localhost:4001/env
+ * curl -u PUT -u "testuser:123" -d "appname=test&key=NODE_ENV&value=production" http://localhost:4001/env
+ * curl -u DELETE -u "testuser:123" -d "appname=test&key=NODE_ENV" http://localhost:4001/env
+ *
+ * Get info about available versions.
+ * @raw: curl -XGET http://localhost:4001/env/version
+ */
+
+app.get('/env/version', _app_.env_version);
+
+/*
+ * Get info about a specific version and see if it's installed
+ * without need of basic auth
+ * @raw: curl -XGET http://localhost:4001/env/:version
+ */
+app.get('/env/version/:version', _app_.check_env_version);
+app.get('/env/:appname', auth, authApp, _app_.env_get);
+app.put('/env', auth, authApp, _app_.env_put);
+app.del('/env/:appname/:key', auth, authApp, _app_.env_delete);
+
+/*
+ * APP NPM Handlers
+ */
var npm = require('./lib/npm');
-// curl -X POST -u "testuser:123" -d "appname=test&package=express" http://localhost:4001/appnpm
-// curl -X POST -u "testuser:123" -d "appname=test&package=express" http://localhost:4001/npm
-// curl -X POST -u "testuser:123" -d "appname=test&package=express,express-extras,foo" http://localhost:4001/npm
-myapp.post('/appnpm', middle.authenticate, middle.authenticate_app, npm.post);
-myapp.post('/npm', middle.authenticate, middle.authenticate_app, npm.post);
-
-// curl -X POST -u "testuser:123" -d "appname=test&domain=<domainname>" http://localhost:4001/appdomains
-// curl -X DELETE -u "testuser:123" -d "appname=test&domain=<domainname>" http://localhost:4001/appdomains
+
+/*
+ * Install package
+ * @raw:
+ * curl -X POST -u "testuser:123" -d "appname=test&package=express" http://localhost:4001/appnpm
+ * curl -X POST -u "testuser:123" -d "appname=test&package=express" http://localhost:4001/npm
+ * curl -X POST -u "testuser:123" -d "appname=test&package=express,express-extras,foo" http://localhost:4001/npm
+ */
+
+app.post('/appnpm', auth, authApp, npm.post);
+app.post('/npm', auth, authApp, npm.post);
+
+/*
+ * Domain handler
+ */
var domains = require('./lib/domains');
-myapp.post('/appdomains', middle.authenticate, middle.authenticate_app, domains.post);
-myapp.del('/appdomains/:appname/:domain', middle.authenticate, middle.authenticate_app, domains.delete);
-myapp.get('/appdomains', middle.authenticate, domains.get);
-// curl -X POST -d "user=username" http://localhost:4001/reset_password
-// curl -X PUT -d "password=newpassword" http://localhost:4001/reset_password/<token>
-var reset_password = require('./lib/reset_password');
-myapp.post('/reset_password', reset_password.post);
-myapp.put('/reset_password/:token', reset_password.put);
+/*
+ * Point domains to nodester
+ * @raw: curl -X POST -u "testuser:123" -d "appname=test&domain=<domainname>" http://localhost:4001/appdomains
+ * curl -X DELETE -u "testuser:123" -d "appname=test&domain=<domainname>" http://localhost:4001/appdomains
+ * @cli: nodester domains
+ */
+app.post('/appdomains', auth, authApp, domains.post);
+app.del('/appdomains/:appname/:domain', auth, authApp, domains.delete);
+app.get('/appdomains', auth, domains.get);
+/*
+ * Reset Password actions
+ * @raw: curl -X POST -d "user=username" http://localhost:4001/reset_password
+ * curl -X PUT -d "password=newpassword" http://localhost:4001/reset_password/<token>
+ */
+var reset_password = require('./lib/reset_password');
+app.post('/reset_password', reset_password.post);
+app.put('/reset_password/:token', reset_password.put);
+
+// default listener
+app.listen(4001);
-myapp.listen(4001);
-console.log('Nodester app started on port 4001');
+log.info('Nodester app started on port %d', app.address().port);
-//The 404 Route (ALWAYS Keep this as the last route)
-myapp.get('/*', function (req, res) {
+app.get('/*', function (req, res) {
throw new NotFound;
});
@@ -267,3 +380,8 @@ function NotFound(msg) {
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
};
+
+// Globalization of log
+process.log = log
+
+/* End of file */
View
29 bin/app_start.sh
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`
-
-./node-config.js
-wait
-source ./.nodester.config
-rm ./.nodester.config
-
-export HOME=$HOME_DIR;
-export PATH="/usr/local/bin:${HOME}/bin:${PATH}";
-
-APPDIR=$APP_DIR
-FHOME=$HOME/forever-app
-
-if [ ! -d $FHOME ]; then
- mkdir -p $FHOME/logs
- mkdir -p $FHOME/pids
-fi
-
-if [ -f $FHOME/logs/forever.log ]; then
- rm -rRf $FHOME/logs/forever.log
-fi
-
-
-wait
-forever start -l logs/forever.log -o $FHOME/logs/app-out.log -e $FHOME/logs/app-err.log -d $APPDIR -p $FHOME $APPDIR/app.js
-wait
-forever list -p $FHOME $APPDIR/app.js
View
20 bin/app_stop.sh
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`
-
-./node-config.js
-wait
-source ./.nodester.config
-rm ./.nodester.config
-
-export HOME=$HOME_DIR;
-export PATH="/usr/local/bin:${HOME}/bin:${PATH}";
-
-APPDIR=$APP_DIR
-
-
-FHOME=$HOME/forever-app
-
-forever stopall -p $FHOME
-
-sleep 1
View
15 bin/forever-app
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`
-
-./node-config.js
-wait
-source ./.nodester.config
-
-export HOME=$HOME_DIR;
-export PATH="/usr/local/bin:${PATH}";
-
-FHOME=$HOME/forever-app/
-
-forever "$@" -p $FHOME
-
View
15 bin/forever-proxy
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`
-
-./node-config.js
-wait
-source ./.nodester.config
-
-export HOME=$HOME_DIR;
-export PATH="/usr/local/bin:${PATH}";
-
-FHOME=$HOME/forever-proxy
-
-
-forever "$@" -p $FHOME
View
35 bin/proxy_start.sh
@@ -1,35 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`
-
-./node-config.js
-wait
-source ./.nodester.config
-wait
-rm ./.nodester.config
-
-export HOME=$HOME_DIR;
-export PATH="/usr/local/bin:${HOME}/bin:${PATH}";
-
-APPDIR=$APP_DIR/proxy
-
-FHOME=$HOME/forever-proxy
-
-
-if [ ! -d $HOME/var ]; then
- mkdir $HOME/var
-fi
-
-if [ ! -d $FHOME ]; then
- mkdir -p $FHOME/logs
- mkdir -p $FHOME/pids
-fi
-
-if [ -f $FHOME/logs/forever.log ]; then
- rm -rRf $FHOME/logs/forever.log
-fi
-
-ulimit -n 99999;
-forever start -l logs/forever.log -o $FHOME/logs/proxy-out.log -e $FHOME/logs/proxy-err.log -d $APPDIR -p $FHOME $APPDIR/proxy.js
-wait
-forever list -p $FHOME $APPDIR/proxy.js
View
20 bin/proxy_stop.sh
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-cd `dirname $0`
-
-./node-config.js
-wait
-source ./.nodester.config
-wait
-rm ./.nodester.config
-
-export HOME=$HOME_DIR;
-export PATH="/usr/local/bin:${HOME}/bin:${PATH}";
-
-APPDIR=$APP_DIR
-
-FHOME=$HOME/forever-proxy
-
-forever stopall -p $FHOME
-
-sleep 1
View
5 install.md
@@ -202,6 +202,8 @@ Also copy `scripts/example_gitrepoclone.sh` to `scripts/gitrepoclone.sh` and upd
The way in how nodester works is pretty straigthforward, so, when a user does a `nodester app restart|start` nodester takes the `node_base_folder` param and it use it to create|mount the sandbox for the app, the `node_base_folder` has the whole environment in which the node-versions are installed and everything that an app needs to work. Soon we are going to publish an example of this environment. So you can install it easily.
+Also you can take a look at [this](https://help.ubuntu.com/community/BasicChroot)
+
### Multiple versions of node:
User: `root`
@@ -297,4 +299,5 @@ Don't like the REST API way? Try the [`nodester-cli`](http://github.com/nodester
### Credits
- [Nodester]("http://nodester.com")
-- `n` By [TJ Holowaychuk]("http://github.com/visionmedia")
+- `n` By [TJ Holowaychuk]("http://github.com/visionmedia")
+
View
1,711 lib/app.js
@@ -1,824 +1,758 @@
-var config = require('../config'),
- fs = require('fs'),
- path = require('path'),
- cradle = require('cradle'),
- lib = require('./lib'),
- unionfs = require('./unionfs').unionfs,
- chroot = require('./chroot').chroot,
- spawn = require('child_process').spawn,
- exec = require('child_process').exec;
-
-
-module.exports = {
- logs: function (req, res, next) {
- var appname = req.appname;
- var user = req.user;
- var app = req.app;
- var app_error_log_sock = path.join(config.opt.apps_home_dir, app.username, app.repo_id + '_chroot', '.nodester', 'logs.sock');
- console.log('Attempting to connect to: ' + app_error_log_sock);
- if (path.existsSync(app_error_log_sock)) {
- var net = require('net');
- var timer = setTimeout(function () {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: 'Timeout getting logs.',
- }) + '\n');
- app_handler.end();
- }, 10000);
- var app_handler = net.createConnection(app_error_log_sock);
- app_handler.once('connect', function () {
- var buff = '';
- app_handler.on('data', function (data) {
- buff += data.toString();
- });
- app_handler.once('end', function () {
- clearTimeout(timer);
- try {
- var logs_strs = JSON.parse(buff);
- var lines = logs_strs['logs'].split('\n');
- } catch (e) {
- var lines = 'Error parsing lines.';
+/*
+ * Nodester :: Open Source Node.JS PaaS
+ * Apps wrapper|controller
+ * @latestUpdate: 30-03-2012
+ * @license GNU Affero
+ */
+
+
+var config = require('../config')
+ , fs = require('fs')
+ , path = require('path')
+ , cradle = require('cradle')
+ , spawn = require('child_process').spawn
+ , exec = require('child_process').exec
+ , lib = require('./lib')
+ , tearDown = lib.tear_down_unionfs_chroot
+ , updateProxy = lib.update_proxytable_map
+ , getDatabase = lib.get_couchdb_database
+ , unionfs = require('./unionfs').unionfs
+ , chroot = require('./chroot').chroot
+ , Controller = module.exports
+ , log = process.log
+ ;
+
+// Shorthand
+
+var cfg = config.opt;
+/*
+ * Get the log.sock and send it to the client
+ * @api public
+ */
+
+// Color helpers
+var COL= {
+ 'green' : ['\033[32m', '\033[39m'],
+ 'magenta' : ['\033[35m', '\033[39m']
+}
+var LOG = {
+ 30:'INFO',
+ 40:'WARN'
+}
+
+var LOGC = {
+ 30:['\033[36m INFO', '\033[39m'].join(''),
+ 40:['\033[31m WARN', '\033[39m'].join('')
+}
+
+Controller.logs = function (req, res, next) {
+ var appname = req.appname
+ , user = req.user
+ , app = req.app
+ , output = ['raw','colorized','normal']
+ , type = output.indexOf(req.query.output) > -1 ? req.query.output : 'colorized'
+ , raw = req.query.raw
+ , app_error_log_sock = path.join(cfg.apps_home_dir, app.username, app.repo_id + '_chroot', '.nodester', 'logs.sock');
+
+ log.info('Attempting to connect to %s\'s %s logs',user,appname);
+ if (path.existsSync(app_error_log_sock)) {
+ var net = require('net');
+ var timer = setTimeout(function () {
+ res.json({
+ status : "failure",
+ message : 'Timeout getting logs.',
+ },500);
+ app_handler.end();
+ }, 10000);
+
+ var app_handler = net.createConnection(app_error_log_sock);
+
+ app_handler.once('connect', function () {
+ var buff = '';
+ app_handler.on('data', function (data) {
+ buff += data.toString();
+ });
+ app_handler.once('end', function () {
+ clearTimeout(timer);
+ try {
+ var logs_strs = buff;
+ logs_strs = JSON.parse(buff)
+ if (logs_str.logs) {
+ var lines = logs_strs.split('\n').map(function(line){
+ line = JSON.parse(line);
+ switch (type) {
+ case 'normal':
+ return line.time +' '+ LOG[parseInt(line.level)]+ ' | '+appname+ ': ' + line.msg
+ break;
+ case 'raw':
+ return line;
+ break;
+ default:
+ return COL.green[0] +line.time + COL.green[1] +' '+ LOGC[parseInt(line.level)]+ ' | '+appname+ ': ' + line.msg ;
+ break;
+ }
+ });
}
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "success",
- lines: lines
- }) + '\n');
- });
+ } catch (e) {
+ var lines = 'Error parsing lines.';
+ }
+ res.json({
+ status: "success",
+ lines: lines
+ },200);
});
+ });
+ } else {
+ res.json({
+ status : 'failure',
+ message : 'No logs available.'
+ },500)
+ }
+}
+
+Controller.gitreset = function (req, res, next) {
+ var appname = req.param("appname").toLowerCase();
+ var user = req.user;
+ var app = req.app;
+ var apps = getDatabase('apps');
+ apps.get(appname, function (err, doc) {
+ if (err) {
+ res.json({
+ status : "failure",
+ message : err.error + ' - ' + err.reason
+ },500)
} else {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
+ log.info('Resetting repo from git: %s', app.repo_id);
+ var app_user_home = path.join(cfg.git_home_dir, app.username, app.repo_id);
+ exec(cfg.app_dir + '/scripts/gitreset.js ' + app_user_home, function () {
+ app_restart(app.repo_id, function() {
+ res.json({
+ status: "success"
+ },200);
+ });
});
- res.end(JSON.stringify({
- status: 'failure',
- message: 'No logs available.'
- }) + '\n');
}
- },
- gitreset: function (req, res, next) {
- var appname = req.param("appname").toLowerCase();
- var user = req.user;
- var app = req.app;
- var apps = lib.get_couchdb_database('apps');
- apps.get(appname, function (err, doc) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- console.log('Resetting repo from git: ', app.repo_id);
- var app_user_home = path.join(config.opt.git_home_dir, app.username, app.repo_id);
- exec(config.opt.app_dir + '/scripts/gitreset.js ' + app_user_home, function () {
- app_restart(app.repo_id, function () {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "success"
- }));
- });
- });
- }
- });
- },
- delete: function (req, res, next) {
- var appname = req.param("appname").toLowerCase();
- var user = req.user;
- var app = req.app;
- var db = lib.get_couchdb_database('apps');
- db.get(appname, function (err, appdoc) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
-
- } else {
- db.remove(appname, appdoc._rev, function (err, resp) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- var app_user_home = path.join(config.opt.apps_home_dir, appdoc.username, appdoc.repo_id);
- var app_git_home = path.join(config.opt.git_home_dir, appdoc.username, appdoc.repo_id);
- var app_rw = app_user_home + '_rw';
- var app_chroot = app_user_home + '_chroot';
- lib.tear_down_unionfs_chroot(config.opt.node_base_folder, app_user_home, app_rw, app_chroot, function () {
- lib.update_proxytable_map(function (err) {
- if (err) {
- console.log('Error updating Proxy! - ' + err);
- }
- app_stop(appdoc.repo_id, function () {
- exec('sudo ' + config.opt.app_dir + '/scripts/removeapp.js ' + app_user_home + ' ' + app_git_home, function () {});
- });
+ });
+}
+
+Controller.delete = function (req, res, next) {
+ var appname = req.param("appname").toLowerCase()
+ , user = req.user
+ , app = req.app
+ , db = getDatabase('apps');
+
+ db.get(appname, function (err, appdoc) {
+ if (err) {
+ res.json({
+ status : "failure",
+ message : err.error + ' - ' + err.reason
+ },500)
+
+ } else {
+ db.remove(appname, appdoc._rev, function (err, resp) {
+ if (err) {
+ res.json({
+ status : "failure",
+ message : err.error + ' - ' + err.reason
+ },500)
+ } else {
+ var app_user_home = path.join(cfg.apps_home_dir, appdoc.username, appdoc.repo_id)
+ , app_git_home = path.join(cfg.git_home_dir, appdoc.username, appdoc.repo_id)
+ , app_rw = app_user_home + '_rw'
+ , app_chroot = app_user_home + '_chroot'
+ ;
+
+ tearDown(cfg.node_base_folder, app_user_home, app_rw, app_chroot, function () {
+ updateProxy(function (err) {
+ if (err) {
+ log.warn('Error updating Proxy! - ' + err);
+ }
+ app_stop(appdoc.repo_id, function () {
+ exec('sudo ' + cfg.app_dir + '/scripts/removeapp.js ' + app_user_home + ' ' + app_git_home,function (){});
});
});
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- "status": "success"
- }));
- }
- });
- }
- });
- },
- put: function (req, res, next) {
- // var appname = req.body.appname.toLowerCase();
- var appname = req.param("appname").toLowerCase();
- var user = req.user;
- var app = req.app;
- var db = lib.get_couchdb_database('apps');
- db.get(appname, function (err, appdoc) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
+ });
+ res.json({
+ "status": "success"
+ });
+ }
+ });
+ }
+ });
+}
+
+Controller.put = function (req, res, next) {
+
+ var appname = req.param("appname").toLowerCase()
+ , user = req.user
+ , app = req.app
+ , db = getDatabase('apps');
+
+ db.get(appname, function (err, appdoc) {
+ if (err) {
+ res.json({
+ status: "failure",
+ message: err.error + ' - ' + err.reason
+ },500);
+ } else {
+ var start = req.body.start
+ , app_user_home = path.join(cfg.apps_home_dir, appdoc.username)
+ , app_home = path.join(app_user_home, appdoc.repo_id)
+ , appDir = path.join(cfg.git_home_dir, appdoc.username, appdoc.repo_id + '.git')
+ , app_repo = cfg.git_user + '@' + cfg.git_dom + ':' + appDir;
+
+ if (typeof start != 'undefined' && start.length > 0) {
+ db.merge(appname, { start: start }, function (err, resp) {
+ res.json({
+ status : "success",
+ port : appdoc.port,
+ gitrepo : app_repo,
+ start : start,
+ running : appdoc.running,
+ pid : appdoc.pid
+ });
});
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
} else {
- var start = req.body.start;
- var app_user_home = path.join(config.opt.apps_home_dir, appdoc.username);
- var app_home = path.join(app_user_home, appdoc.repo_id);
- var app_repo = config.opt.git_user + '@' + config.opt.git_dom + ':' + path.join(config.opt.git_home_dir, appdoc.username, appdoc.repo_id + '.git');
- if (typeof start != 'undefined' && start.length > 0) {
- db.merge(appname, {
- start: start
- }, function (err, resp) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "success",
- port: appdoc.port,
- gitrepo: app_repo,
- start: start,
- running: appdoc.running,
- pid: appdoc.pid
- }));
- });
- } else {
- var running = req.body.running;
- switch (running) {
+ var running = req.body.running;
+ switch (running) {
case "true":
if (appdoc.running == "true") {
- res.writeHead(408, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
+ res.json({
status: "failure - application already running."
- }));
+ });
} else {
app_start(appdoc.repo_id, function (rv, pid) {
- var success = "false",
- running = "failed-to-start";
+ var success = "false"
+ , running = "failed-to-start";
if (rv === true) {
success = "success";
running = "true";
- lib.update_proxytable_map(function (err) {
+ updateProxy(function (err) {
if (err) {
- console.log('Error updating Proxy! - ' + err);
+ log.warn('Error updating Proxy! - ' + err);
}
});
}
- db.merge(appname, {
- running: running,
- pid: pid
- }, function (err, resp) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: success,
- port: appdoc.port,
- gitrepo: app_repo,
- start: appdoc.start,
- running: running,
- pid: pid
- }));
+ db.merge(appname, { running: running, pid: pid}, function (err, resp) {
+ res.json({
+ status : success,
+ port : appdoc.port,
+ gitrepo : app_repo,
+ start : appdoc.start,
+ running : running,
+ pid : pid
});
});
+ });
+ }
+ break;
+ /* endcase running=true */
+
+ case "restart":
+ app_restart(app.repo_id, function (rv, pid) {
+ var success = "false"
+ , running = "failed-to-restart";
+
+ if (rv === true) {
+ success = "success";
+ running = "true";
}
- break;
- case "restart":
- app_restart(app.repo_id, function (rv, pid) {
+ db.merge(appname, { running: running, pid: pid }, function (err, resp) {
+ res.json({
+ status : success,
+ port : appdoc.port,
+ gitrepo : app_repo,
+ start : appdoc.start,
+ running : running,
+ pid : pid
+ });
+ });
+ });
+ break;
+ /*endcase running=restart */
+
+ case "false":
+ if (app.running != 'true') {
+ res.json({
+ status: "failure - application already stopped."
+ },408);
+ } else {
+ app_stop(app.repo_id, function (rv) {
var success = "false",
- running = "failed-to-restart";
+ running = "failed-to-stop";
if (rv === true) {
success = "success";
- running = "true";
- }
- db.merge(appname, {
- running: running,
- pid: pid
- }, function (err, resp) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
+ running = "false";
+ updateProxy(function (err) {
+ if (err) {
+ log.warn('Error updating Proxy! - ' + err);
+ }
});
- res.end(JSON.stringify({
- status: success,
- port: appdoc.port,
- gitrepo: app_repo,
- start: appdoc.start,
- running: running,
- pid: pid
- }));
- });
- });
- break;
- case "false":
- if (app.running != 'true') {
- res.writeHead(408, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure - application already stopped."
- }));
- } else {
- app_stop(app.repo_id, function (rv) {
- var success = "false",
- running = "failed-to-stop";
- if (rv === true) {
- success = "success";
- running = "false";
- lib.update_proxytable_map(function (err) {
- if (err) {
- console.log('Error updating Proxy! - ' + err);
- }
- });
- }
- db.merge(appname, {
- running: running,
- pid: 'unknown'
- }, function (err, resp) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: success,
- port: appdoc.port,
- gitrepo: app_repo,
- start: appdoc.start,
- running: running,
- pid: 'unknown'
- }));
+ }
+ db.merge(appname, { running: running, pid: 'unknown'}, function (err, resp) {
+ res.json({
+ status : success,
+ port : appdoc.port,
+ gitrepo : app_repo,
+ start : appdoc.start,
+ running : running,
+ pid : 'unknown'
});
});
- }
- break;
- default:
- res.writeHead(400, {
- 'Content-Type': 'application/json'
});
- res.end(JSON.stringify({
- status: "failure",
- message: "Invalid action."
- }) + "\n");
- break;
}
+ break;
+ /* endcase running=false */
+ default:
+ res.json({
+ status : "failure",
+ message : "Invalid action."
+ },400);
+ break;
+ /* end switch case */
}
}
- });
- },
+ }
+ });
+}
+Controller.app_start = function (req, res, next) {
- app_start: function (req, res, next) {
- var repo_id = req.query.repo_id;
- var restart_key = req.query.restart_key;
- if (restart_key != config.opt.restart_key) {
- res.writeHead(403, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to start - invalid restart key"
- }));
- return;
- } else {
- app_start(repo_id, function (rv, err) {
- if (rv === false) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to start - " + err
- }));
- } else {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "started"
- }));
- }
- }, true);
- }
- },
- app_stop: function (req, res, next) {
- var repo_id = req.query.repo_id;
- var restart_key = req.query.restart_key;
- if (restart_key != config.opt.restart_key) {
- res.writeHead(403, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to start - invalid restart key"
- }));
- return;
- } else {
- app_stop(repo_id, function (rv) {
- if (rv === false) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to stop"
- }));
- } else {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "stop"
- }));
- }
- });
- }
- },
- app_restart: function (req, res, next) {
- var repo_id = req.query.repo_id;
- var restart_key = req.query.restart_key;
- if (restart_key != config.opt.restart_key) {
- res.writeHead(403, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to start - invalid restart key"
- }));
- return;
- } else {
- app_restart(repo_id, function (rv) {
- if (rv === false) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to restart"
- }));
- } else {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "restarted"
- }));
- }
- }, true);
- }
- },
- get: function (req, res, next) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "success",
- port: req.app.port,
- gitrepo: config.opt.git_user + '@' + config.opt.git_dom + ':' + path.join(config.opt.git_home_dir, req.app.username, req.app.repo_id + '.git'),
- start: req.app.start,
- running: req.app.running,
- pid: req.app.pid
- }));
- },
- post: function (req, res, next) {
- var appname = req.body.appname;
- if (!appname){
- appname = req.param("appname").toLowerCase();
- };
- if (!/^[A-Z0-9_\-\.]*$/gi.test(appname)){
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: "Appname Invalid"
- }));
- return;
- }
- var start = req.body.start;
- if (!appname) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: "Appname Required"
- }));
- return;
- }
- if (!start) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: "Start File Required"
- }));
- return;
- }
- var user = req.user;
- var apps = lib.get_couchdb_database('apps');
- apps.get(appname, function (err, doc) {
- if (err) {
- if (err.error == 'not_found') {
- var nextport = lib.get_couchdb_database('nextport');
- nextport.get('port', function (err, next_port) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- var appport = next_port.address;
- var repo_id = next_port._rev;
- nextport.merge('port', {
- address: appport + 1
- }, function (err, resp) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- apps.save(appname, {
- start: start,
- port: appport,
- username: user._id,
- repo_id: repo_id,
- running: false,
- pid: 'unknown',
- env: {}
- }, function (err, resp) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- var repos = lib.get_couchdb_database('repos');
- repos.save(repo_id, {
- appname: appname,
- username: user._id
- }, function (err, resp) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- var cmd = 'sudo ' + config.opt.app_dir + '/scripts/gitreposetup.sh ' + [config.opt.app_dir, config.opt.git_home_dir, user._id, repo_id, start, config.opt.userid, config.opt.git_user, config.opt.apps_home_dir].join(' ');
- console.log('gitsetup cmd: %s', cmd);
- exec(cmd, function (err, stdout, stderr) {
- if (err) console.error('gitsetup error: %s', err);
- if (stdout.length > 0) console.log('gitsetup stdout: %s', stdout);
- if (stderr.length > 0) console.error('gitsetup stderr: %s', stderr);
- });
- // var gitsetup = spawn('/usr/bin/env sudo ' + config.opt.app_dir + '/scripts/gitreposetup.sh', [config.opt.app_dir, config.opt.git_home_dir, user._id, repo_id, start, config.opt.userid, config.opt.git_user]);
- //Added logging to the reposetup script
- // gitsetup.stdout.on('data', function (data) {
- // console.log('git setup stdout: ' + data);
- //});
- // gitsetup.stderr.on('data', function (data) {
- // console.error('git setup stderr: ' + data);
- //});
- // Respond to API request
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "success",
- port: appport,
- gitrepo: config.opt.git_user + '@' + config.opt.git_dom + ':' + path.join(config.opt.git_home_dir, user._id, repo_id + '.git'),
- start: start,
- running: false,
- pid: "unknown"
- }));
- lib.update_proxytable_map(function (err) {
- if (err) {
- console.log('Error updating Proxy! - ' + err);
- }
- // Not sure if the user needs to be made aware in case of these errors. Admins should be though.
- });
- }
- });
- }
- });
- }
- });
- }
- });
- } else {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- }
+
+ var repo_id = req.query.repo_id
+ , restart_key = req.query.restart_key;
+
+ if (restart_key != cfg.restart_key) {
+ res.json({
+ status: "failed to start - invalid restart key"
+ },403);
+ return;
+ } else {
+ app_start(repo_id, function (rv, err) {
+ if (rv === false) {
+ res.json({
+ status: "failed to start - " + err
+ },200);
} else {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
+ res.json({
+ status: "started"
+ },200);
+ }
+ }, true);
+ }
+}
+
+Controller.app_stop = function (req, res, next) {
+
+ var repo_id = req.query.repo_id
+ , restart_key = req.query.restart_key;
+
+ if (restart_key != cfg.restart_key) {
+ res.json({
+ status: "failed to start - invalid restart key"
+ }, 403);
+ return;
+ } else {
+ app_stop(repo_id, function (rv) {
+ if (rv === false) {
+ res.json({
+ status: "failed to stop"
+ });
+ } else {
+ res.json({
+ status: "stop"
});
- res.end(JSON.stringify({
- status: "failure",
- message: "app exists"
- }));
}
});
- },
- audit:function(req,res,next){
- var db = lib.get_couchdb_database('apps');
- // abuser just for fun :)
- req.on('data',function(abuser){
- abuser = JSON.parse(abuser.toString());
- db.view('nodeapps/pid',{key:abuser.PID,limit:1},function(error,doc){
- var structure ={};
- if (doc && doc.length==1) {
- structure = {
- repo :doc.value[0],
- username:doc.value[1],
- appname :doc.value[3]
- };
- var msg = ' '+structure.username+'\'s '+structure.appname+' app.';
- if (abuser.code == 'N10'){
- msg = 'Stoping ' + msg;
- app_stop(structure.repo, function(rv){
- if (rv === false) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to stop"
- }));
+ }
+ /* end of app_stop */
+}
+
+Controller.app_restart= function (req, res, next) {
+
+ var repo_id = req.query.repo_id
+ , restart_key = req.query.restart_key;
+
+ if (restart_key != cfg.restart_key) {
+ res.json({
+ status: "failed to start - invalid restart key"
+ },403);
+ return;
+ } else {
+ app_restart(repo_id, function (rv) {
+ if (rv === false) {
+ res.json({
+ status: "failed to restart"
+ });
+ } else {
+ res.json({
+ status: "restarted"
+ });
+ }
+ }, true);
+ }
+}
+
+Controller.get = function (req, res, next) {
+
+ var location = path.join(cfg.git_home_dir, req.app.username, req.app.repo_id + '.git')
+ , gitRepo = cfg.git_user + '@' + cfg.git_dom + ':' + location;
+
+ res.json({
+ status : "success",
+ port : req.app.port,
+ gitrepo : gitRepo,
+ start : req.app.start,
+ running : req.app.running,
+ pid : req.app.pid
+ });
+
+}
+
+Controller.post = function (req, res, next) {
+
+ var appname = req.body.appname;
+
+ if (!appname){
+ appname = req.param("appname").toLowerCase();
+ }
+ var start = req.body.start;
+
+ if (!appname) {
+ res.json({
+ status: "failure",
+ message: "Appname Required"
+ },500);
+ return;
+ }
+ if (!start) {
+ res.json({
+ status: "failure",
+ message: "Start File Required"
+ },500);
+ return;
+ }
+ var user = req.user
+ , apps = getDatabase('apps');
+
+ apps.get(appname, function (err, doc) {
+ if (err) {
+ if (err.error == 'not_found') {
+ var nextport = getDatabase('nextport');
+ nextport.get('port', function (err, next_port) {
+ if (err) {
+ res.json({
+ status : "failure",
+ message : err.error + ' - ' + err.reason
+ },500);
+ } else {
+ var appport = next_port.address
+ , repo_id = next_port._rev;
+
+ nextport.merge('port', { address: appport + 1 }, function (err, resp) {
+ if (err) {
+ res.json({
+ status : "failure",
+ message : err.error + ' - ' + err.reason
+ },500);
} else {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
+ apps.save(appname, {
+ start : start,
+ port : appport,
+ username : user._id,
+ repo_id : repo_id,
+ running : false,
+ pid : 'unknown',
+ env : {}
+ }, function (err, resp) {
+ if (err) {
+ res.json({
+ status: "failure",
+ message: err.error + ' - ' + err.reason
+ },500);
+ } else {
+ var repos = getDatabase('repos');
+ repos.save(repo_id, {
+ appname : appname,
+ username : user._id
+ }, function (err, resp) {
+ if (err) {
+ res.json({
+ status : "failure",
+ message : err.error + ' - ' + err.reason
+ },500);
+ } else {
+ var params = [cfg.app_dir, cfg.git_home_dir, user._id, repo_id, start, cfg.userid, cfg.git_user, cfg.apps_home_dir]
+ var cmd = 'sudo ' + cfg.app_dir + '/scripts/gitreposetup.sh ' + params.join(' ');
+
+ log.info('gitsetup cmd: %s', cmd);
+ exec(cmd, function (err, stdout, stderr) {
+ if (err) log.error('gitsetup error: %s', err);
+ if (stdout.length > 0) log.info('gitsetup stdout: %s', stdout);
+ if (stderr.length > 0) log.error('gitsetup stderr: %s', stderr);
+ });
+ // Respond to API request
+ var gitRepo = cfg.git_user + '@' + cfg.git_dom + ':' + path.join(cfg.git_home_dir, user._id, repo_id + '.git');
+ res.json({
+ status : "success",
+ port : appport,
+ gitrepo : gitRepo,
+ start : start,
+ running : false,
+ pid : "unknown"
+ });
+ updateProxy(function (err) {
+ if (err) {
+ log.warn('Error updating Proxy! - ' + err);
+ }
+ // Not sure if the user needs to be made aware in case of these errors. Admins should be though.
+ });
+ }
+ });
+ }
});
- res.end(JSON.stringify({
- status: "stop"
- }));
}
});
- } else if (abuser.code == 'N11'){
- msg = 'Restarting '+msg;
- app_restart(structure.repo, function (rv) {
- if (rv === false) {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failed to restart",
- code:200
- }));
- } else {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "restarted",
- code:200
- }));
- }
- }, true);
}
- console.log(msg);
- } else {
- // Kill it with fire dude
- res.json({code:200});
- res.end();
- }
- });
- })
- },
- env_get: function (req, res, next) {
- var appname = req.appname.toLowerCase();
- var db = lib.get_couchdb_database('apps');
- db.get(appname, function (err, appdoc) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
});
- res.end(JSON.stringify({
+ } else {
+ res.json({
status: "failure",
message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- var start = req.body.start;
- db.get(appname, function (err, doc) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- res.writeHead(200, {
- 'Content-Type': 'application/json'
- });
- // expose general variables, by default the doc.port and req.app.port
- // have the value, (req.app.port inherits from middle#authenticated_app)
- // And the NODE_ENV it's setting up manually by the user or by the nodester
- // instance
- doc.env['app_port'] = doc.port || ((req.app && req.app.port) ? req.app.port : 80);
- doc.env['NODE_ENV'] = doc.env['NODE_ENV'] || 'production';
- res.end(JSON.stringify({
- status: "success",
- message: doc.env || {}
- }));
- }
- });
- }
- });
- },
- env_version: function(req, res, next){
- lib.check_available_versions(function(d){
- if (typeof d == 'array' || typeof d == 'object') {
- d = d.map(function(v){
- return v.trim().substr(0,7);
- });
+ },500);
}
+ } else {
res.json({
- main: process.version,
- available: d || 'Error'
- });
- });
- },
- check_env_version: function(req, res, next){
- var version = req.param('version') || false,
- res_code = 404,
- msg = 'Invalid version, or not_found';
- // just avoiding potential errors
- if (version && lib.node_versions().indexOf(version)!==-1) {
- res_code = 200;
- msg = 'node-v'+version+ ' it\'s available';
- }
- res.json({
- version: version,
- statusCode: res_code,
- msg: msg
- });
- },
- env_put: function (req, res, next) {
- var appname = req.body.appname.toLowerCase();
- var db = lib.get_couchdb_database('apps');
- var key = req.body.key,
- value = req.body.value;
- if (!key || !value) {
- res.writeHead(400, {
- 'Content-Type': 'application/json'
+ status : "failure",
+ message : "app exists"
});
- res.end(JSON.stringify({
- status: "failure",
- message: "Must specify both key and value."
- }) + "\n");
- return;
}
- db.get(appname, function (err, appdoc) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
+ });
+}
+
+Controller.audit = function(req, res, next) {
+ var db = getDatabase('apps');
+ // abuser just for fun :)
+ req.on('data',function(abuser){
+ abuser = JSON.parse(abuser.toString());
+ db.view('nodeapps/pid',{key:abuser.PID,limit:1},function(error,doc){
+ var structure ={};
+ if (doc && doc.length==1) {
+ structure = {
+ repo : doc.value[0],
+ username : doc.value[1],
+ appname : doc.value[3]
+ };
+ var msg = ' ' + structure.username + '\'s ' + structure.appname + ' app.';
+ if (abuser.code == 'N10'){
+ msg = 'Stoping ' + msg;
+ app_stop(structure.repo, function(rv){
+ if (rv === false) {
+ res.json({
+ status: "failed to stop"
+ });
+ } else {
+ res.json({
+ status: "stop"
+ });
+ }
+ });
+ } else if (abuser.code == 'N11'){
+ msg = 'Restarting '+msg;
+ app_restart(structure.repo, function (rv) {
+ if (rv === false) {
+ res.json({
+ status: "failed to restart",
+ code:200
+ });
+ } else {
+ res.json|({
+ status: "restarted",
+ code:200
+ });
+ }
+ }, true);
+ }
+ log.info(msg);
} else {
- env_update(res, db, appname, appdoc, key, value);
+ // Kill it with fire dude
+ res.json({code:200});
+ res.end();
}
});
- },
- env_delete: function (req, res, next) {
- var appname = req.param("appname").toLowerCase();
- var db = lib.get_couchdb_database('apps');
- var key = req.param("key");
- if (!key) {
- res.writeHead(400, {
- 'Content-Type': 'application/json'
+ })
+ /* deprecated */
+}
+
+Controller.env_get = function (req, res, next) {
+
+ var appname = req.appname.toLowerCase();
+ var db = getDatabase('apps');
+ db.get(appname, function (err, appdoc) {
+ if (err) {
+ res.json({
+ status : "failure",
+ message : err.error + ' - ' + err.reason
+ },500);
+ } else {
+ var start = req.body.start;
+ db.get(appname, function (err, doc) {
+ if (err) {
+ res.json({
+ status: "failure",
+ message: err.error + ' - ' + err.reason
+ },500);
+ } else {
+ /*
+ * expose general variables, by default the doc.port and req.app.port
+ * have the value, (req.app.port inherits from middle#authenticated_app)
+ * And the NODE_ENV it's setting up manually by the user or by the nodester
+ * instance
+ */
+ doc.env['app_port'] = doc.port || ((req.app && req.app.port) ? req.app.port : 80);
+ doc.env['NODE_ENV'] = doc.env['NODE_ENV'] || 'production';
+ res.json({
+ status: "success",
+ message: doc.env || {}
+ });
+ }
});
- res.end(JSON.stringify({
- status: "failure",
- message: "Must specify key."
- }) + "\n");
- return;
}
- db.get(appname, function (err, appdoc) {
- if (err) {
- res.writeHead(500, {
- 'Content-Type': 'application/json'
- });
- res.end(JSON.stringify({
- status: "failure",
- message: err.error + ' - ' + err.reason
- }) + '\n');
- } else {
- env_update(res, db, appname, appdoc, key, undefined);
- }
- });
- },
- restartByName:function(req,res,next){
- restart_by_name(req.params.appname, function(e,d){
- res.json({error:e, response:d});
+ });
+ /* end getEnviromental vars */
+}
+
+Controller.env_version = function(req, res, next) {
+ lib.check_available_versions(function(d){
+ if (typeof d == 'array' || typeof d == 'object') {
+ d = d.map(function(v){
+ return v.trim().substr(0,7);
+ });
+ }
+ res.json({
+ main: process.version,
+ available: d || 'Error'
});
- }
-};
+ });
+}
-var env_update = function (res, db, appname, appdoc, key, value) {
- var env = {};
- if (appdoc.env) {
- Object.keys(appdoc.env).forEach(function (k) {
- env[k] = appdoc.env[k];
- });
+Controller.check_env_version = function(req, res, next) {
+
+ var version = req.param('version') || false
+ , res_code = 404
+ , msg = 'Invalid version, or not_found';
+
+ // just avoiding potential errors
+ if (version && lib.node_versions().indexOf(version)!==-1) {
+ res_code = 200;
+ msg = 'node-v'+version+ ' it\'s available';
+ }
+ res.json({
+ version: version,
+ statusCode: res_code,
+ msg: msg
+ });
+}
+
+Controller.env_put= function (req, res, next) {
+ var appname = req.body.appname.toLowerCase()
+ , db = getDatabase('apps')
+ , key = req.body.key
+ , value = req.body.value;
+
+ if (!key || !value) {
+ res.json({
+ status: "failure",
+ message: "Must specify both key and value."
+ },400);
+ return;
+ }
+ db.get(appname, function (err, appdoc) {
+ if (err) {
+ res.json({
+ status: "failure",
+ message: err.error + ' - ' + err.reason
+ },500);
+ } else {
+ env_update(res, db, appname, appdoc, key, value);
}
- if (value !== undefined) {
- env[key] = value;
+ });
+}
+
+Controller.env_delete=function (req, res, next) {
+ var appname = req.param("appname").toLowerCase()
+ , db = getDatabase('apps')
+ , key = req.param("key");
+
+ if (!key) {
+ res.json({
+ status : "failure",
+ message : "Must specify key."
+ },400);
+ return;
+ }
+ db.get(appname, function (err, appdoc) {
+ if (err) {
+ res.json({
+ status: "failure",
+ message: err.error + ' - ' + err.reason
+ },500);