Permalink
Browse files

Project Snapshot

  • Loading branch information...
0 parents commit 9b4e0753a0309d62a349798b74c790a2331a9421 @groundwater committed Jan 17, 2013
Showing with 314 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +8 −0 README.md
  3. +19 −0 envvars.js
  4. +85 −0 index.js
  5. +53 −0 logger.js
  6. +39 −0 monitor.js
  7. +27 −0 ng.js
  8. +14 −0 package.json
  9. +48 −0 procfile.js
  10. +20 −0 subproc.js
@@ -0,0 +1 @@
+node_modules
@@ -0,0 +1,8 @@
+## Overview
+
+- init runs general
+- general runs the application
+
+## AWS
+
+- init script _should_ read environment from `user-data`
@@ -0,0 +1,19 @@
+function Environment(){}
+
+module.exports = {
+ Make: function(file){
+ // Make Environment from File or String
+ var env = new Environment();
+ file.split(/\n/).forEach(function(line){
+ var items = line.split('=',2);
+
+ if(items.length < 2) return;
+
+ var key = items[0];
+ var value = items[1];
+
+ env[key] = value;
+ })
+ return env;
+ }
+}
@@ -0,0 +1,85 @@
+var http = require('http');
+var util = require('util');
+var cp = require('child_process');
+var path = require('path');
+var fs = require('fs');
+
+var Logger = require('./logger');
+var Monitor = require('./monitor');
+var Procfile = require('./procfile');
+var ProcessBuilder = require('./subproc');
+var Environment = require('./envvars');
+
+var globalLogger = Logger.New(process.stdout);
+
+function start(envs,procfile,options){
+
+ globalLogger.info('Starting All Processes');
+
+ procfile.keys().forEach(function(key){
+
+ // Write file to _both_ STDOUT and a Log File
+ var logpath = path.join( options.logdir, key + '.log' )
+ var stream = fs.createWriteStream( logpath, {flags: 'a', mode:'0644'} );
+ var logview = Logger.New(process.stdout);
+ var logfile = Logger.New(stream);
+
+ logview.prefix = util.format('%s'.white, key);
+ logview.info('Starting Processes:',key);
+
+ var command = procfile.process(key);
+ var builder = ProcessBuilder.Create(command);
+
+ // Add Environment Variables
+ builder.env = envs;
+
+ var monitor = Monitor.Create(builder);
+
+ // Log to multiple destinations
+ monitor.emitter.on('stdout', function(data){
+ logview.pipe(data);
+ logfile.pipe(data);
+ });
+ monitor.emitter.on('stderr', function(data){
+ logview.pipe(data);
+ logfile.pipe(data);
+ });
+ monitor.emitter.on('exit', function(code){
+ logview.done('Process #code{%s} Exited with Code #code{%d}', key, code);
+ logfile.done('Process #code{%s} Exited with Code #code{%d}', key, code);
+ });
+
+ monitor.begin(key);
+
+ });
+}
+
+function attack(options){
+ // Load Procfile and Start Processes
+ var procfile = Procfile.Load(options.procfile);
+ var chunks = [];
+ var environ;
+
+ // Load Environment from a File or STDIN
+ if(options.environ == '-'){
+ globalLogger.info('Loading Environment from STDIN');
+ process.stdin.setEncoding('ascii');
+ process.stdin.resume();
+ environ = process.stdin;
+ }else{
+ globalLogger.info('Loading Environment from %s',options.environ);
+ environ = fs.createReadStream(options.environ);
+ }
+
+ environ.on('data',function(chunk){
+ chunks.push(chunk);
+ })
+
+ environ.on('end',function(){
+ var envs = Environment.Make( chunks.join('') );
+ start(envs,procfile,options);
+ })
+
+}
+
+module.exports.attack = attack
@@ -0,0 +1,53 @@
+var colors = require('colors')
+var util = require('util');
+
+colors.setTheme({
+ code: 'grey'
+});
+
+function colorize(string){
+ return string.replace(/\#([^{]+){(.*?)}/g, function(match,color,value){
+ return value[color]
+ });
+}
+
+function Logger(pipe){
+ this._pipe = pipe;
+ this.prefix = '';
+}
+
+Logger.prototype.append = function(type){
+ var date = new Date();
+ var append = [
+ date.toDateString().grey,
+ date.toLocaleTimeString().grey,
+ this.prefix,
+ type,
+ ': '
+ ];
+ return append.join(' ');
+}
+
+Logger.prototype.log = function(string){
+ this._pipe.write( string + '\n');
+}
+
+Logger.prototype.done = function(){
+ var fmt = util.format.apply(null,arguments);
+ this.log( this.append('[DONE]'.blue) + colorize(fmt));
+}
+
+Logger.prototype.info = function(){
+ var fmt = util.format.apply(null,arguments);
+ this.log( this.append('[INFO]'.cyan) + colorize(fmt));
+}
+
+Logger.prototype.pipe = function(data){
+ this._pipe.write( this.append('[DATA]'.grey) + data.toString() );
+}
+
+module.exports = {
+ New: function(pipe){
+ return new Logger(pipe);
+ }
+}
@@ -0,0 +1,39 @@
+var events = require('events');
+
+function Viagra(processBuilder){
+ this.processBuilder = processBuilder;
+ this.emitter = new events.EventEmitter();
+}
+
+Viagra.prototype._run = function(){
+ var _this = this;
+ this.process = this.processBuilder.start();
+ var onStdout = function(data){
+ _this.emitter.emit('stdout',data);
+ }
+ var onStderr = function(data){
+ _this.emitter.emit('stderr',data);
+ }
+ this.process.stdout.on('data', onStdout);
+ this.process.stderr.on('data', onStderr);
+ this.process.on('exit',function(code){
+ _this.emitter.emit('exit', code);
+ _this._run();
+ })
+}
+
+Viagra.prototype.begin = function(key){
+ if(this.key) throw new Error('Already Started');
+ this.key = key;
+ this._run();
+}
+
+Viagra.prototype.stop = function(){
+
+}
+
+module.exports = {
+ Create: function(pb){
+ return new Viagra(pb);
+ }
+}
27 ng.js
@@ -0,0 +1,27 @@
+#!/usr/bin/env node
+
+var commander = require('commander');
+var colors = require('colors');
+
+var general = require('./index');
+
+commander
+.option('-P, --procfile <FILE>', 'Load Processes from FILE', 'Procfile')
+.option('-E, --environ <PATH>', 'Read In Environment from PATH (use - for STDIN)', '-')
+.option('-L, --logdir <BASE>', 'Use BASE directory for logging application','.')
+
+commander
+.command('start')
+.description('Run a Procfile')
+.action(function(command){
+ general.attack(commander);
+})
+
+commander.parse(process.argv);
+
+if(commander.args.length==0) {
+ console.log(" __ ___ ___ __ ".grey)
+ console.log(" / _` |__ |\\ | |__ |__) /\\ | ".grey)
+ console.log(" \\__> |___ | \\| |___ | \\ /--\\ |___ ".grey)
+ commander.help();
+}
@@ -0,0 +1,14 @@
+{
+ "name": "general",
+ "version": "0.0.1",
+ "description": "Polyglot Server Application Running",
+ "main": "index.js",
+ "bin": {
+ "ng": "ng.js"
+ },
+ "dependencies": {
+ "colors": "~0.6.0-1",
+ "commander": "~1.1.1"
+ },
+ "license": "MIT"
+}
@@ -0,0 +1,48 @@
+var fs = require('fs');
+
+function Command(string){
+ if (!string) throw new Error('Cannot Initialize an Empty Command')
+ this._commands = string.trim().split(' ')
+}
+
+Command.prototype.commands = function(){
+ return this._commands.slice(1);
+}
+
+Command.prototype.command = function(){
+ return this._commands[0];
+}
+
+function Procfile(){}
+
+Procfile.prototype.keys = function(){
+ return Object.keys(this._proces);
+}
+
+Procfile.prototype.process = function(key){
+ return this._proces[key];
+}
+
+module.exports = {
+ Load : function(file){
+ // Load a Procfile from file
+ var data = fs.readFileSync(file).toString().split(/\n/);
+ var proc = new Procfile();
+ proc._proces = {};
+ data.forEach(function(line){
+ var trimmed = line.trim();
+ var items = trimmed.split(':',2);
+
+ if(items.length != 2) return;
+
+ var key = items[0];
+ var value = items[1];
+ proc._proces[key] = new Command(value);
+ })
+ return proc;
+ },
+ Make : function(string){
+ // Make a Procfile from a string
+ throw new Error('Method Not Implemented')
+ }
+}
@@ -0,0 +1,20 @@
+var cp = require('child_process');
+
+function ProcessBuilder(){}
+
+ProcessBuilder.prototype.start = function(){
+ var options = {
+ env: this.env
+ }
+ return cp.spawn(this.command.command(), this.command.commands(), options);
+}
+
+module.exports = {
+ Create: function(command){
+ // Create a SubProcess from a Command object
+ var sub = new ProcessBuilder();
+ sub.command = command
+
+ return sub;
+ }
+}

0 comments on commit 9b4e075

Please sign in to comment.