diff --git a/app.js b/app.js new file mode 100644 index 0000000..83fefb3 --- /dev/null +++ b/app.js @@ -0,0 +1,60 @@ +var express = require('express'); +var path = require('path'); +var favicon = require('serve-favicon'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); + +var routes = require('./routes/index'); +var users = require('./routes/users'); + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'ejs'); + +// uncomment after placing your favicon in /public +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', users); +app.use('/api', routes); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +// error handlers + +// development error handler +// will print stacktrace +if (app.get('env') === 'development') { + app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + }); +} + +// production error handler +// no stacktraces leaked to user +app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); +}); + + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100755 index 0000000..eafbd45 --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('manager:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '2000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/lxc.js b/lxc.js new file mode 100644 index 0000000..73098a5 --- /dev/null +++ b/lxc.js @@ -0,0 +1,125 @@ +module.exports = function(config){ + + var obj = {}; + var child = require('child'), + sshBind = config.sshBind || false; + + //http://stackoverflow.com/questions/10530532/ + function textToArgs(s){ + var words = []; + s.replace(/"([^"]*)"|'([^']*)'|(\S+)/g,function(g0,g1,g2,g3){ words.push(g1 || g2 || g3 || '')}); + return words; + } + + var sysExec = function(command, onData, onClose){ + + onData = onData || function(){}; + onClose = onClose || function(){}; + + if (sshBind != false) + { + var runCommand = sshBind.slice(); + runCommand.push(command); + } else { + var runCommand = textToArgs(command); + } + + var errors = ''; + + child({ + command: runCommand.slice(0,1)[0], + args: runCommand.slice(1), + cbStdout: function(data){ onData(''+data) }, + cbStderr: function(data){ errors+=data; onData(''+data) }, + cbClose: function(exitCode){ onClose(exitCode == 0 ? null:exitCode, errors) } + }).start(); + }; + + + obj.create = function(name, template, config, cbComplete, cbData){ + sysExec('lxc-create -n '+name+' -t '+template, cbComplete, cbData); + }; + + obj.clone = function(name, base_name, cbComplete, cbData){ + sysExec('lxc-clone -o '+base_name+ ' -n '+name +' -B overlayfs -s', cbComplete, cbData); + }; + + obj.destroy = function(name, cbComplete, cbData){ + sysExec('lxc-destroy -n '+ name, cbComplete, cbData); + }; + + + obj.start = function(name, cbComplete, cbData){ + var cmd = 'lxc-start --name '+name+' --daemon'; + console.log('start cmd\n', cmd, '\n'); + sysExec(cmd, cbComplete, cbData); + }; + + obj.startEphemeral = function(name, base_name, cbComplete, cbData){ + + var output = ''; + sysExec('lxc-start-ephemeral -o '+base_name+ ' -n '+name +' --union-type overlayfs -d', function(data){output+=data}, function(error){ + if(output.match("doesn't exist.")) return cbData({status: 500, error: "doesn't exist."}); + if(output.match("already exists.")) return cbData({status: 500, error: "already exists"}); + if(output.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)) return cbData({status: 200, state:'RUNNING', ip: output.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0]}); + cbData({'?': '?', data: output, name: name, base_name: base_name}); + }); + }; + + obj.stop = function(name, cbComplete, cbData){ + sysExec('lxc-stop -n '+ name, cbComplete, cbData); + }; + + + obj.freeze = function(name, cbComplete, cbData){ + sysExec('lxc-freeze -n '+name, cbComplete, cbData); + }; + + obj.unfreeze = function(name, cbComplete, cbData){ + sysExec('lxc-unfreeze -n '+name, cbComplete, cbData); + }; + + obj.info = function(name, cbComplete, cbData){ + + var output = ''; + sysExec('lxc-info -n'+name, function(data){output+=data}, function(error){ + if(output.match("doesn't exist")) return cbData({state: 'NULL'}); + var info = {}; + output = output.replace(/\suse/ig, '').replace(/\sbytes/ig, '').split("\n").slice(0,-1); + for(var i in output){ + var temp = output[i].split(/\:\s+/); + info[temp[0].toLowerCase().trim()] = temp[1].trim(); + } + cbData(info); + }); + }; + + obj.list = function(cbData){ + + var output = ''; + sysExec('lxc-ls --fancy', function(data){output+=data}, function(error){ + + output = output.split("\n"); + var keys = output.splice(0,1)[0].split(/\s+/).slice(0,-1); + keys = keys.map(function(v){return v.toLowerCase()}); + output = output.slice(0).splice(1).slice(0,-1); + + var info = []; + + for (var i in output) + { + + var aIn = output[i].split(/\s+/).slice(0,-1), + mapOut = {}; + aIn.map( function(v,i){ mapOut[keys[i]] = v; } ); + info.push(mapOut); + + } + + cbData(info); + }); + }; + + + return obj; +}; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..dde6f7f --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "manager", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "body-parser": "~1.13.2", + "cookie-parser": "~1.3.5", + "debug": "~2.2.0", + "ejs": "~2.3.3", + "express": "~4.13.1", + "morgan": "~1.6.1", + "serve-favicon": "~2.3.0" + } +} \ No newline at end of file diff --git a/public/images/gears.gif b/public/images/gears.gif new file mode 100644 index 0000000..6c51c2f Binary files /dev/null and b/public/images/gears.gif differ diff --git a/public/images/load.gif b/public/images/load.gif new file mode 100644 index 0000000..ab67ac0 --- /dev/null +++ b/public/images/load.gif @@ -0,0 +1,24 @@ +loading.io - Your SVG + GIF Ajax Loading Icons
LOADING.IO
Login With Facebook

{{auth.failed}}
LoginSign up
Sign up
Log In
{{n.message}}
Build Your Ajax
Loading
Icons with

SVG / CSS / GIF !
RecordingGenerating
{{build.percent}}%
{{2 * build.size}}px

save
Run
Stop
Get SVGSVG N/A
Get CSSCSS N/A
Make GIFGIF N/A
{{t[0]}}
want more? share it!

Examples

SVG Loader

You can use SVG loader just like using an image. For example, with <img> tag:

<img src="triangle.svg">

or as background image:



CSS Loader

CSS loader has two parts: stylesheet and HTML part. Stylesheet is embraced in <style> tag so you can copy the file content into the place you want the icon to show.

To increase reusability, you can separate stylesheet from html part into a standalone css file. For example:

<link rel="stylesheet" type="text/css" href="examples/battery.css"> +<div class='uil-battery-demo-css' style='-webkit-transform:scale(0.6)'> + <outer></outer> + <inner></inner> + <inner></inner> + <inner></inner> + <inner></inner> +</div>

will look like this:


GIF Loader

Use GIF loader in an <img> tag or as background of another element:

<img src="spinner.gif"> +<div style="background:url(spinner.gif) no-repeat center center;width:32px;height:32px;"></div>

+For example:



Browser Compatibility

tl;dr

+Use GIF loader if you need compatibility in Internet Explorer.


SVG Loader ( not for IE )

All SVG loaders use SMIL to animate elements. Modern browsers support SVG and SMIL except Internet Explorer:

  • SVG: IE ≥ 9.0
  • SMIL: IE doesn't Support


CSS Loader ( IE ≥ 10.0 )

All CSS loaders use CSS3 Animation to animate elements. Modern browsers support CSS3 except Internet Explorer:

  • CSS3 Animation: IE ≥ 10.0
  • CSS3 Transform: IE ≥ 10.0 (partially)


+GIF Loader ( cross-platform )

All modern browsers support GIF loader. Use GIF loader to ensure optimized browser compatibility.



This Tool

This tool is tested against following browsers:

  • Google Chrome 34.0.
  • Firefox 28.0
  • Safari 7.03
  • Opera 18.0.
  • Internet Explorer 11.0

It's built upon bootstrap, angularjs, canvg, gif.js and web workers. It's known that some browsers ( e.g., IE10 ) are not supported, so please upgrade your browser if you want to use this tool.


Comments

\ No newline at end of file diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 0000000..9453385 --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,8 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..1c75508 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,81 @@ +var express = require('express'); +var router = express.Router(); +var extend = require('node.extend'); +var redis = require("redis"); +var client = redis.createClient(); +var lxc = require('../lxc')({sshBind: ['/usr/bin/ssh', 'virt@127.0.0.1']}); +//lxc.startEphemeral('ubuntu_template', 'ue0', function(){console.log('cb1', arguments)}, function(){console.log('cb2', arguments)}) + +router.get('/start/:name', function(req, res, next){ + lxc.start(req.params.name, null, function(status, message){ + if(status){ + res.json({status: 500, name: req.params.name, message: message}); + }else{ + setTimeout(function() { + lxc.info(req.params.name, null, function(data){ + var domain = req.query.domain || 'vm42.us'; + domain = req.params.name+'.'+domain; + client.SADD("hosts", domain, function(){}); + + var ip = data.ip + ':5000'; + client.HSET(domain, "ip", ip, redis.print); + client.HSET(domain, "updated", (new Date).getTime(), redis.print); + client.hset(domain, "include", "proxy.include"); + res.json({status: 200, info: data}); + }); + }, 5000); + + } + }); +}); + +router.get('/live/:template/:name', function(req, res, next){ + lxc.startEphemeral(req.params.name, req.params.template, null, function (data) { + res.json(data); + }); +}); + +router.get('/stop/:name', function(req, res, next){ + lxc.stop(req.params.name, null, function(data, message){ + if(data){ + res.json({status: 500, name: req.params.name, message: message}); + }else{ + res.json({status: 200}); + } + }); +}); + +router.get('/clone/:template/:name', function(req, res, next){ + lxc.clone(req.params.name, req.params.template, function(message){ + if( message.match(/Created container/) ){ + res.json({status: 200}); + }else{ + res.json({status: 500, message: message}); + } + }); +}); + +router.get('/destroy/:name', function(req, res, next){ + lxc.destroy(req.params.name, null, function(data, message){ + if(data){ + res.json({status: 500, message: message}); + }else{ + res.json({status: 200}); + } + }); +}); + +router.get('/info/:name', function(req, res, next){ + lxc.info(req.params.name, null, function(data){ + res.json(data); + }); +}); + +router.get('/list', function(req, res, next) { + lxc.list(function(data){ + res.json(data); + }); +}); + +module.exports = router; +// {"changed":true,"filter":false,"title":"index.js","tooltip":"/routes/index.js","value":"var express = require('express');\nvar router = express.Router();\nvar extend = require('node.extend');\nvar redis = require(\"redis\");\nvar client = redis.createClient();\nvar lxc = require('../lxc')({sshBind: ['/usr/bin/ssh', 'virt@127.0.0.1']});\n//lxc.startEphemeral('ubuntu_template', 'ue0', function(){console.log('cb1', arguments)}, function(){console.log('cb2', arguments)})\n\nrouter.get('/start/:name', function(req, res, next){\n lxc.start(req.params.name, null, function(status, message){\n if(status){\n res.json({status: 500, name: req.params.name, message: message});\n }else{\n setTimeout(function() {\n lxc.info(req.params.name, null, function(data){\n var domain = req.query.domain || 'vm42.us';\n domain = req.params.name+'.'+domain;\n client.SADD(\"hosts\", domain, function(){});\n \n var ip = data.ip + ':5000';\n client.HSET(domain, \"ip\", ip, redis.print);\n client.HSET(domain, \"updated\", (new Date).getTime(), redis.print);\n client.hset(domain, \"include\", \"proxy.include\");\n res.json({status: 200, info: data});\n });\n }, 5000);\n\n }\n });\n});\n\nrouter.get('/live/:template/:name', function(req, res, next){\n lxc.startEphemeral(req.params.name, req.params.template, null, function (data) {\n res.json(data);\n });\n});\n\nrouter.get('/stop/:name', function(req, res, next){\n lxc.stop(req.params.name, null, function(data, message){\n if(data){\n res.json({status: 500, name: req.params.name, message: message});\n }else{\n res.json({status: 200});\n }\n });\n});\n\nrouter.get('/clone/:template/:name', function(req, res, next){\n lxc.clone(req.params.name, req.params.template, function(message){\n if( message.match(/Created container/) ){\n res.json({status: 200});\n }else{\n res.json({status: 500, message: message});\n }\n });\n});\n\nrouter.get('/destroy/:name', function(req, res, next){\n lxc.destroy(req.params.name, null, function(data, message){\n if(data){\n res.json({status: 500, message: message});\n }else{\n res.json({status: 200});\n }\n });\n});\n\nrouter.get('/info/:name', function(req, res, next){\n lxc.info(req.params.name, null, function(data){\n res.json(data);\n });\n});\n\nrouter.get('/list', function(req, res, next) {\n lxc.list(function(data){\n res.json(data); \n });\n});\n\nmodule.exports = router;","undoManager":{"mark":90,"position":100,"stack":[[{"start":{"row":32,"column":27},"end":{"row":32,"column":30},"action":"remove","lines":["par"],"id":37},{"start":{"row":32,"column":27},"end":{"row":32,"column":33},"action":"insert","lines":["params"]}],[{"start":{"row":32,"column":33},"end":{"row":32,"column":34},"action":"insert","lines":["."],"id":38}],[{"start":{"row":32,"column":34},"end":{"row":32,"column":35},"action":"insert","lines":["n"],"id":39}],[{"start":{"row":32,"column":35},"end":{"row":32,"column":36},"action":"insert","lines":["a"],"id":40}],[{"start":{"row":32,"column":36},"end":{"row":32,"column":37},"action":"insert","lines":["m"],"id":41}],[{"start":{"row":32,"column":37},"end":{"row":32,"column":38},"action":"insert","lines":["e"],"id":42}],[{"start":{"row":32,"column":38},"end":{"row":32,"column":39},"action":"insert","lines":[","],"id":43}],[{"start":{"row":32,"column":39},"end":{"row":32,"column":40},"action":"insert","lines":[" "],"id":44}],[{"start":{"row":32,"column":40},"end":{"row":32,"column":41},"action":"insert","lines":["p"],"id":45}],[{"start":{"row":32,"column":41},"end":{"row":32,"column":42},"action":"insert","lines":["a"],"id":46}],[{"start":{"row":32,"column":42},"end":{"row":32,"column":43},"action":"insert","lines":["q"],"id":47}],[{"start":{"row":32,"column":42},"end":{"row":32,"column":43},"action":"remove","lines":["q"],"id":48}],[{"start":{"row":32,"column":41},"end":{"row":32,"column":42},"action":"remove","lines":["a"],"id":49}],[{"start":{"row":32,"column":40},"end":{"row":32,"column":41},"action":"remove","lines":["p"],"id":50}],[{"start":{"row":32,"column":40},"end":{"row":32,"column":41},"action":"insert","lines":["r"],"id":51}],[{"start":{"row":32,"column":41},"end":{"row":32,"column":42},"action":"insert","lines":["e"],"id":52}],[{"start":{"row":32,"column":42},"end":{"row":32,"column":43},"action":"insert","lines":["q"],"id":53}],[{"start":{"row":32,"column":43},"end":{"row":32,"column":44},"action":"insert","lines":[","],"id":54}],[{"start":{"row":32,"column":43},"end":{"row":32,"column":44},"action":"remove","lines":[","],"id":55}],[{"start":{"row":32,"column":43},"end":{"row":32,"column":44},"action":"insert","lines":["."],"id":56}],[{"start":{"row":32,"column":44},"end":{"row":32,"column":45},"action":"insert","lines":["p"],"id":57}],[{"start":{"row":32,"column":44},"end":{"row":32,"column":45},"action":"remove","lines":["p"],"id":58},{"start":{"row":32,"column":44},"end":{"row":32,"column":50},"action":"insert","lines":["params"]}],[{"start":{"row":32,"column":50},"end":{"row":32,"column":51},"action":"insert","lines":[","],"id":59}],[{"start":{"row":32,"column":50},"end":{"row":32,"column":51},"action":"remove","lines":[","],"id":60}],[{"start":{"row":32,"column":50},"end":{"row":32,"column":51},"action":"insert","lines":["."],"id":61}],[{"start":{"row":32,"column":51},"end":{"row":32,"column":52},"action":"insert","lines":["t"],"id":62}],[{"start":{"row":32,"column":52},"end":{"row":32,"column":53},"action":"insert","lines":["e"],"id":63}],[{"start":{"row":32,"column":51},"end":{"row":32,"column":53},"action":"remove","lines":["te"],"id":64},{"start":{"row":32,"column":51},"end":{"row":32,"column":59},"action":"insert","lines":["template"]}],[{"start":{"row":32,"column":59},"end":{"row":32,"column":60},"action":"insert","lines":[","],"id":65}],[{"start":{"row":32,"column":60},"end":{"row":32,"column":61},"action":"insert","lines":[" "],"id":66}],[{"start":{"row":32,"column":61},"end":{"row":32,"column":62},"action":"insert","lines":["n"],"id":67}],[{"start":{"row":32,"column":62},"end":{"row":32,"column":63},"action":"insert","lines":["u"],"id":68}],[{"start":{"row":32,"column":63},"end":{"row":32,"column":64},"action":"insert","lines":["k"],"id":69}],[{"start":{"row":32,"column":64},"end":{"row":32,"column":65},"action":"insert","lines":["k"],"id":70}],[{"start":{"row":32,"column":64},"end":{"row":32,"column":65},"action":"remove","lines":["k"],"id":71}],[{"start":{"row":32,"column":63},"end":{"row":32,"column":64},"action":"remove","lines":["k"],"id":72}],[{"start":{"row":32,"column":63},"end":{"row":32,"column":64},"action":"insert","lines":["l"],"id":73}],[{"start":{"row":32,"column":64},"end":{"row":32,"column":65},"action":"insert","lines":["l"],"id":74}],[{"start":{"row":32,"column":65},"end":{"row":32,"column":66},"action":"insert","lines":["m"],"id":75}],[{"start":{"row":32,"column":65},"end":{"row":32,"column":66},"action":"remove","lines":["m"],"id":76}],[{"start":{"row":32,"column":64},"end":{"row":32,"column":65},"action":"remove","lines":["l"],"id":77}],[{"start":{"row":32,"column":63},"end":{"row":32,"column":64},"action":"remove","lines":["l"],"id":78}],[{"start":{"row":32,"column":62},"end":{"row":32,"column":63},"action":"remove","lines":["u"],"id":79}],[{"start":{"row":32,"column":61},"end":{"row":32,"column":62},"action":"remove","lines":["n"],"id":80}],[{"start":{"row":32,"column":60},"end":{"row":32,"column":61},"action":"remove","lines":[" "],"id":81}],[{"start":{"row":32,"column":60},"end":{"row":32,"column":61},"action":"insert","lines":[" "],"id":82}],[{"start":{"row":32,"column":61},"end":{"row":32,"column":62},"action":"insert","lines":["n"],"id":83}],[{"start":{"row":32,"column":62},"end":{"row":32,"column":63},"action":"insert","lines":["u"],"id":84}],[{"start":{"row":32,"column":63},"end":{"row":32,"column":64},"action":"insert","lines":["l"],"id":85}],[{"start":{"row":32,"column":64},"end":{"row":32,"column":65},"action":"insert","lines":["l"],"id":86}],[{"start":{"row":32,"column":65},"end":{"row":32,"column":66},"action":"insert","lines":[","],"id":87}],[{"start":{"row":32,"column":66},"end":{"row":32,"column":67},"action":"insert","lines":[" "],"id":88}],[{"start":{"row":32,"column":67},"end":{"row":32,"column":68},"action":"insert","lines":["f"],"id":89}],[{"start":{"row":32,"column":68},"end":{"row":32,"column":69},"action":"insert","lines":["i"],"id":90}],[{"start":{"row":32,"column":68},"end":{"row":32,"column":69},"action":"remove","lines":["i"],"id":91}],[{"start":{"row":32,"column":68},"end":{"row":32,"column":69},"action":"insert","lines":["u"],"id":92}],[{"start":{"row":32,"column":69},"end":{"row":32,"column":70},"action":"insert","lines":["n"],"id":93}],[{"start":{"row":32,"column":67},"end":{"row":32,"column":70},"action":"remove","lines":["fun"],"id":94},{"start":{"row":32,"column":67},"end":{"row":34,"column":5},"action":"insert","lines":["function function_name(argument) {"," // body..."," }"]}],[{"start":{"row":32,"column":76},"end":{"row":32,"column":89},"action":"remove","lines":["function_name"],"id":95}],[{"start":{"row":32,"column":77},"end":{"row":32,"column":85},"action":"remove","lines":["argument"],"id":96},{"start":{"row":32,"column":77},"end":{"row":32,"column":78},"action":"insert","lines":["d"]}],[{"start":{"row":32,"column":78},"end":{"row":32,"column":79},"action":"insert","lines":["a"],"id":97}],[{"start":{"row":32,"column":79},"end":{"row":32,"column":80},"action":"insert","lines":["t"],"id":98}],[{"start":{"row":32,"column":80},"end":{"row":32,"column":81},"action":"insert","lines":["a"],"id":99}],[{"start":{"row":33,"column":9},"end":{"row":33,"column":18},"action":"remove","lines":["/ body..."],"id":100}],[{"start":{"row":33,"column":8},"end":{"row":33,"column":9},"action":"remove","lines":["/"],"id":101}],[{"start":{"row":33,"column":8},"end":{"row":33,"column":9},"action":"insert","lines":["r"],"id":102}],[{"start":{"row":33,"column":9},"end":{"row":33,"column":10},"action":"insert","lines":["e"],"id":103}],[{"start":{"row":33,"column":9},"end":{"row":33,"column":10},"action":"remove","lines":["e"],"id":104}],[{"start":{"row":33,"column":9},"end":{"row":33,"column":10},"action":"insert","lines":["s"],"id":105}],[{"start":{"row":33,"column":9},"end":{"row":33,"column":10},"action":"remove","lines":["s"],"id":106}],[{"start":{"row":33,"column":8},"end":{"row":33,"column":9},"action":"remove","lines":["r"],"id":107}],[{"start":{"row":33,"column":8},"end":{"row":33,"column":9},"action":"insert","lines":["r"],"id":108}],[{"start":{"row":33,"column":9},"end":{"row":33,"column":10},"action":"insert","lines":["e"],"id":109}],[{"start":{"row":33,"column":10},"end":{"row":33,"column":11},"action":"insert","lines":["s"],"id":110}],[{"start":{"row":33,"column":11},"end":{"row":33,"column":12},"action":"insert","lines":["."],"id":111}],[{"start":{"row":33,"column":12},"end":{"row":33,"column":13},"action":"insert","lines":["j"],"id":112}],[{"start":{"row":33,"column":13},"end":{"row":33,"column":14},"action":"insert","lines":["s"],"id":113}],[{"start":{"row":33,"column":12},"end":{"row":33,"column":14},"action":"remove","lines":["js"],"id":114},{"start":{"row":33,"column":12},"end":{"row":33,"column":16},"action":"insert","lines":["json"]}],[{"start":{"row":33,"column":16},"end":{"row":33,"column":18},"action":"insert","lines":["()"],"id":115}],[{"start":{"row":33,"column":17},"end":{"row":33,"column":18},"action":"insert","lines":["d"],"id":116}],[{"start":{"row":33,"column":18},"end":{"row":33,"column":19},"action":"insert","lines":["a"],"id":117}],[{"start":{"row":33,"column":19},"end":{"row":33,"column":20},"action":"insert","lines":["t"],"id":118}],[{"start":{"row":33,"column":20},"end":{"row":33,"column":21},"action":"insert","lines":["a"],"id":119}],[{"start":{"row":33,"column":22},"end":{"row":33,"column":23},"action":"insert","lines":["l"],"id":120}],[{"start":{"row":33,"column":22},"end":{"row":33,"column":23},"action":"remove","lines":["l"],"id":121}],[{"start":{"row":33,"column":22},"end":{"row":33,"column":23},"action":"insert","lines":[";"],"id":122}],[{"start":{"row":34,"column":6},"end":{"row":34,"column":7},"action":"insert","lines":[";"],"id":123}],[{"start":{"row":52,"column":53},"end":{"row":52,"column":54},"action":"insert","lines":[";"],"id":124}],[{"start":{"row":62,"column":35},"end":{"row":62,"column":36},"action":"insert","lines":[";"],"id":125}],[{"start":{"row":22,"column":67},"end":{"row":22,"column":68},"action":"insert","lines":[";"],"id":126}],[{"start":{"row":5,"column":19},"end":{"row":5,"column":20},"action":"insert","lines":["."],"id":127}],[{"start":{"row":23,"column":0},"end":{"row":23,"column":4},"action":"remove","lines":[" "],"id":128}],[{"start":{"row":23,"column":0},"end":{"row":23,"column":4},"action":"remove","lines":[" "],"id":129}],[{"start":{"row":23,"column":0},"end":{"row":23,"column":4},"action":"remove","lines":[" "],"id":130}],[{"start":{"row":23,"column":0},"end":{"row":23,"column":4},"action":"remove","lines":[" "],"id":131}],[{"start":{"row":23,"column":0},"end":{"row":23,"column":3},"action":"remove","lines":[" "],"id":132}],[{"start":{"row":23,"column":0},"end":{"row":23,"column":4},"action":"insert","lines":[" "],"id":133}],[{"start":{"row":23,"column":4},"end":{"row":23,"column":8},"action":"insert","lines":[" "],"id":134}],[{"start":{"row":23,"column":8},"end":{"row":23,"column":12},"action":"insert","lines":[" "],"id":135}],[{"start":{"row":23,"column":12},"end":{"row":23,"column":16},"action":"insert","lines":[" "],"id":136}],[{"start":{"row":23,"column":16},"end":{"row":23,"column":20},"action":"insert","lines":[" "],"id":137}]]},"ace":{"folds":[],"scrolltop":0,"scrollleft":0,"selection":{"start":{"row":23,"column":20},"end":{"row":23,"column":20},"isBackwards":false},"options":{"guessTabSize":true,"useWrapMode":false,"wrapToView":true},"firstLineState":{"row":92,"mode":"ace/mode/javascript"}},"timestamp":1448259407910} \ No newline at end of file diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..d30f494 --- /dev/null +++ b/routes/users.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +router.get('/', function(req, res, next) { + res.render('index') +}); + +module.exports = router; diff --git a/stuff.md b/stuff.md new file mode 100644 index 0000000..92a1987 --- /dev/null +++ b/stuff.md @@ -0,0 +1,5 @@ +## Auto start +`@reboot /usr/local/bin/forever start -o /var/log/forver.out.log -e /var/log/sorver.err.log -c "/usr/local/bin/codebox run -p 5000" /workspace/` +http://stackoverflow.com/a/13388741/3140931 + + diff --git a/views/error.ejs b/views/error.ejs new file mode 100644 index 0000000..7cf94ed --- /dev/null +++ b/views/error.ejs @@ -0,0 +1,3 @@ +

<%= message %>

+

<%= error.status %>

+
<%= error.stack %>
diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 0000000..2ff58d5 --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + +

Start will take atlest 5 seconds!

+ +
    +
  1. + {{ name }} | {{ state }} | {{ ip }} + +
    + + + +
    + {{{ url }}} + {{{ clone }}} + {{{ message }}} +
    +
  2. +
+ +