diff options
author | Aristeidis Iliopoulos <ailiopou@cisco.com> | 2016-09-15 11:36:44 -0700 |
---|---|---|
committer | Aristeidis Iliopoulos <ailiopou@cisco.com> | 2016-09-15 18:21:20 -0700 |
commit | 417c664ee2bc2a032969639d53b43b732d428e9e (patch) | |
tree | 3f17e15f6d0861bb0e35d79771e42e3b7a2d92ea /vpp-userdemo/ui/backend | |
parent | 764d4be74089c635598c6f139afc087d1ac55659 (diff) |
Added GUI for tutorials that runs entirely inside the VM
-fixed issue with webserver not spinning up properly
Change-Id: I3724f1640ba2b84b7d84fab29febbbd047120812
Signed-off-by: Aristeidis Iliopoulos <ailiopou@cisco.com>
Diffstat (limited to 'vpp-userdemo/ui/backend')
-rw-r--r-- | vpp-userdemo/ui/backend/.bowerrc | 3 | ||||
-rw-r--r-- | vpp-userdemo/ui/backend/bower.json | 25 | ||||
-rw-r--r-- | vpp-userdemo/ui/backend/gulpfile.js | 173 | ||||
-rw-r--r-- | vpp-userdemo/ui/backend/package.json | 39 | ||||
-rw-r--r-- | vpp-userdemo/ui/backend/server.js | 133 |
5 files changed, 373 insertions, 0 deletions
diff --git a/vpp-userdemo/ui/backend/.bowerrc b/vpp-userdemo/ui/backend/.bowerrc new file mode 100644 index 0000000..7fb7ce4 --- /dev/null +++ b/vpp-userdemo/ui/backend/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "../frontend/bower_components/" +}
\ No newline at end of file diff --git a/vpp-userdemo/ui/backend/bower.json b/vpp-userdemo/ui/backend/bower.json new file mode 100644 index 0000000..204c6dd --- /dev/null +++ b/vpp-userdemo/ui/backend/bower.json @@ -0,0 +1,25 @@ +{ + "name": "iliogr", + "authors": [ + "Aristeidis Iliopoulos <ailiopou@cisco.com>" + ], + "description": "scaffold", + "main": "", + "license": "MIT", + "homepage": "", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "angular": "^1.5.7", + "angular-ui-router": "^0.3.1", + "angular-material": "^1.0.9", + "normalize-css": "^4.2.0", + "jquery": "^3.0.0", + "ngclipboard": "^1.1.1" + } +} diff --git a/vpp-userdemo/ui/backend/gulpfile.js b/vpp-userdemo/ui/backend/gulpfile.js new file mode 100644 index 0000000..5f66cec --- /dev/null +++ b/vpp-userdemo/ui/backend/gulpfile.js @@ -0,0 +1,173 @@ +var gulp = require('gulp'); +var concat = require('gulp-concat'); +var rename = require('gulp-rename'); +var cleanCSS = require('gulp-clean-css'); +var uglify = require('gulp-uglify'); +var mainBowerFiles = require('main-bower-files'); +var gulpFilter = require('gulp-filter'); +var imagemin = require('gulp-imagemin'); +var flatten = require('gulp-flatten'); +var jshint = require('gulp-jshint'); +var sass = require('gulp-sass'); +var watch = require('gulp-watch'); +var wiredep = require('wiredep').stream; +var series = require('stream-series'); +var inject = require('gulp-inject'); +var clean = require('gulp-clean'); +var livereload = require('gulp-livereload'); + +var paths = { + source: { + bower: '../frontend/bower_components', + images: '../frontend/assets/images/**', + js: '../frontend/**/*.js', + html: '../frontend/**/*.html', + index: '../frontend/index.html', + sass: '../frontend/assets/sass/*.scss', + fonts: '../frontend/assets/fonts/**' + }, + target: { + dev: '../dist.dev', + prod: '../dist.prod', + imagesDev: '../dist.dev/images', + imagesProd: '../dist.prod/images', + htmlDev: '../dist.dev/html', + htmlProd: '../dist.prod/html', + cssDev: '../dist.dev/css', + cssProd: '../dist.prod/cssProd', + jsDev: '../dist.dev/js', + jsProd: '../dist.prod/js', + vendorDev: '../dist.dev/vendor', + vendorProd: '../dist.prod/vendor', + indexDev: '../dist.dev/html/index.html', + indexProd: '../dist.prod/html/index.html', + fontsDev: '../dist.dev/fonts', + fontsProd: '../dist.prod/fonts' + } +} + +gulp.task('bower', function() { + + var jsFilter = gulpFilter(paths.source.bower+'/**/*.js', {restore: true}) + var cssFilter = gulpFilter(paths.source.bower+'/**/*.css', {restore: true}) + + return gulp.src(mainBowerFiles()) + .pipe(jsFilter) + .pipe(concat('vendor.js')) + .pipe(gulp.dest(paths.target.vendorDev)) + .pipe(rename('vendor.min.js')) + .pipe(gulp.dest(paths.target.vendorProd)) + .pipe(jsFilter.restore) + .pipe(cssFilter) + .pipe(concat('vendor.css')) + .pipe(gulp.dest(paths.target.vendorDev)) + .pipe(rename('vendor.min.css')) + .pipe(cleanCSS()) + .pipe(gulp.dest(paths.target.vendorProd)) + .pipe(cssFilter.restore) + .pipe(livereload()); +}); + + +gulp.task('images', function() { + return gulp.src(paths.source.images) + .pipe(imagemin({ progressive: true })) + .pipe(flatten()) + .pipe(gulp.dest(paths.target.imagesDev)) + .pipe(gulp.dest(paths.target.imagesProd)) + .pipe(livereload()); +}); + +gulp.task('lint', function() { + return gulp.src(['!'+paths.source.bower+'/**', paths.source.js]) + .pipe(jshint()) + .pipe(jshint.reporter('default')); +}); + +gulp.task('html', function() { + return gulp.src(['!'+paths.source.bower+'/**', '!'+paths.source.index, paths.source.html]) + .pipe(flatten()) + .pipe(gulp.dest(paths.target.htmlDev)) + .pipe(gulp.dest(paths.target.htmlProd)) + .pipe(livereload()); +}); + +gulp.task('fonts', function() { + return gulp.src([paths.source.fonts]) + .pipe(flatten()) + .pipe(gulp.dest(paths.target.fontsDev)) + .pipe(gulp.dest(paths.target.fontsProd)); +}); + +gulp.task('js', function() { + return gulp.src(['!'+paths.source.bower+'/**', paths.source.js]) + .pipe(concat('app.js')) + .pipe(gulp.dest(paths.target.jsDev)) + .pipe(rename('app.min.js')) + .pipe(gulp.dest(paths.target.jsProd)) + .pipe(livereload()); +}); + +gulp.task('sass', function() { + return gulp.src(paths.source.sass) + .pipe(sass()).on('error', onError) + .pipe(gulp.dest(paths.target.cssDev)) + .pipe(gulp.dest(paths.target.cssProd)) + .pipe(livereload()); +}); + +gulp.task('watch', function() { + livereload.listen(); + gulp.watch([paths.source.images], ['images']); + gulp.watch([paths.source.html], ['html']); + gulp.watch([paths.source.bower], ['bower']); + gulp.watch(['!'+paths.source.bower+'/**', paths.source.js], ['lint', 'js']); + gulp.watch(paths.source.sass, ['sass']); +}); + +gulp.task('clean', function() { + gulp.src(paths.target.dev, {read: false}) + .pipe(clean({force: true})) + gulp.src(paths.target.prod, {read: false}) + .pipe(clean({force: true})) +}); + +gulp.task('injectDev', ['bower', 'sass', 'js'], function () { + var target = gulp.src(paths.source.index); + var sources = gulp.src([paths.target.vendorDev+'/*.js', paths.target.vendorDev+'/*.css', paths.target.cssDev+'/*.css', paths.target.jsDev+'/*.js'], {read: false}); + return target.pipe(inject(sources, {addRootSlash : false, + transform : function(filePath, file, i, length){ + var newPath = filePath.replace('dist.dev/', ''); + if(filePath.match(/.css/)){ + return '<link rel="stylesheet" href="'+newPath+'">' + } + else + return '<script src="'+newPath+'"></script>'; + }})) + .pipe(gulp.dest(paths.target.htmlDev)); +}); + +gulp.task('injectProd', ['bower', 'sass', 'js'], function () { + var target = gulp.src(paths.source.index); + var sources = gulp.src([paths.target.vendorProd+'/*.js', paths.target.vendorProd+'/*.css', paths.target.cssProd+'/*.css', paths.target.jsProd+'/*.js'], {read: false}); + return target.pipe(inject(sources, {addRootSlash : false, + transform : function(filePath, file, i, length){ + var newPath = filePath.replace('dist.prod/', ''); + if(filePath.match(/.css/)){ + return '<link rel="stylesheet" href="'+newPath+'">' + } + else + return '<script src="'+newPath+'"></script>'; + }})) + .pipe(gulp.dest(paths.target.htmlProd)); +}); + +function onError(err) { + console.log(err); + this.emit('end'); +} + +gulp.task('default', ['bower', 'lint', 'js', 'sass', 'images', 'fonts', 'html', 'injectDev', 'injectProd', 'watch']); + + + diff --git a/vpp-userdemo/ui/backend/package.json b/vpp-userdemo/ui/backend/package.json new file mode 100644 index 0000000..1aedcab --- /dev/null +++ b/vpp-userdemo/ui/backend/package.json @@ -0,0 +1,39 @@ +{ + "name": "vppsb", + "version": "1.0.0", + "description": "", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Aris Iliopoulos", + "license": "ISC", + "dependencies": { + "body-parser": "^1.15.1", + "express": "^4.13.4", + "ip": "^1.1.3", + "ssh2": "^0.5.1", + "untildify": "^3.0.2", + "winston": "^2.2.0" + }, + "devDependencies": { + "gulp": "^3.9.1", + "gulp-clean": "^0.3.2", + "gulp-clean-css": "^2.0.10", + "gulp-concat": "^2.6.0", + "gulp-filter": "^4.0.0", + "gulp-flatten": "^0.3.0", + "gulp-imagemin": "^3.0.1", + "gulp-jshint": "^2.0.1", + "gulp-livereload": "^3.8.1", + "gulp-rename": "^1.2.2", + "gulp-sass": "^2.3.2", + "gulp-inject": "^4.1.0", + "gulp-uglify": "^1.5.4", + "gulp-watch": "^4.3.8", + "jshint": "^2.9.2", + "main-bower-files": "^2.13.1", + "stream-series": "^0.1.1", + "wiredep": "^4.0.0" + } +} diff --git a/vpp-userdemo/ui/backend/server.js b/vpp-userdemo/ui/backend/server.js new file mode 100644 index 0000000..3523708 --- /dev/null +++ b/vpp-userdemo/ui/backend/server.js @@ -0,0 +1,133 @@ +// ========================================================================= +// ==================== get the packages we need =========================== +// ========================================================================= +var express = require('express'); +var app = express(); +var v1 = new express.Router(); +var bodyParser = require('body-parser'); +var ip = require('ip'); +var fs = require('fs'); +var path = require('path'); +var fs = require('fs'); +var untildify = require('untildify'); +var Client = require('ssh2').Client; +var conn = new Client(); +var PATH = untildify('~/'); +var winston = require('winston'); +var exec = require('child_process').exec; +// =========================================================================== +// ================== Initialize the logging system ========================== +// =========================================================================== +var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.File)({ + name: 'info-file', + filename: 'node-info.log', + level: 'info' + }), + new (winston.transports.File)({ + name: 'error-file', + filename: 'node-error.log', + level: 'error' + }) + ] +}); +// ========================================================================== +// ====================== start the webserver ============================== +// ========================================================================== +var server = app.listen(5000, ip.address(), function() { + console.log('Server running at http://'+ip.address()+':'+5000); + logger.log('info', 'Server running at http://'+ip.address()+':'+5000); +}); +// =========================================================================== +// ================ Initialize express dependencies ========================== +// =========================================================================== +app.use(bodyParser.urlencoded({extended: false})); +app.use(bodyParser.json()); +app.use(express.static(__dirname + '/../dist.prod')); +// Removing Angular's annoying # from the URL +app.get('/', function(req, res) { + res.sendFile(path.join(__dirname + '/../dist.prod/html/index.html')); +}); +// =========================================================================== +// ================= Initialize the API routes =============================== +// =========================================================================== +app.use('/api/v1', v1); + +var TUTORIALS_PATH = __dirname+'/../../tutorials'; +var CMDS_REGEXP = /CMD\+=\("(.*)"\)/gmi; +var INSTR_REGEXP = /INSTR\+=\("(.*)"\)/gmi; +var C1_IP_REGEXP = /C1_IP="(.*)"/gmi; +var C1_GW_REGEXP = /C1_GW="(.*)"/gmi; +var C2_IP_REGEXP = /C2_IP="(.*)"/gmi; +var C2_GW_REGEXP = /C2_GW="(.*)"/gmi; + + +function grabTutorials(req, res, next){ + + var TUTORIALS = []; + fs.readdir(TUTORIALS_PATH, function(err, data) { + if (err) { + return console.log(err); + } +else + for(var x = 0; x < data.length; x++){ + if(data[x].match(/^[^.]+$|.*\.sh/g)){ + TUTORIALS.push(data[x]); + } + } + logger.log('info', 'Tutorials are sent to the client'); + res.send(TUTORIALS); + }); +} + +function grabFile(req, res, next){ + + fs.readFile(TUTORIALS_PATH+'/'+req.params.tutorial, 'utf8', function (err,data) { + if (err) { + return console.log(err); + } + var CMD = ''; + var commands = []; + var INSTR = ''; + var instructions = []; + var IP1 = ''; + var IP2 = ''; + var GW1 = ''; + var GW2 = ''; + + CMD = data.match(CMDS_REGEXP); + INSTR = data.match(INSTR_REGEXP); + IP1 = data.match(C1_IP_REGEXP); + IP2 = data.match(C2_IP_REGEXP); + GW1 = data.match(C1_GW_REGEXP); + GW2 = data.match(C2_GW_REGEXP); + + IP1 = IP1[0].replace('C1_IP="', "").replace('"', ""); + IP2 = IP2[0].replace('C2_IP="', "").replace('"', ""); + GW1 = GW1[0].replace('C1_GW="', "").replace('"', ""); + GW2 = GW2[0].replace('C2_GW="', "").replace('"', ""); + + for(var x = 0; x < INSTR.length; x++){ + commands.push(CMD[x].replace('CMD+=("', "").replace('")', "")); + instructions.push(INSTR[x].replace('INSTR+=("', "").replace('")', "")); + } + exec('/vagrant/netns.sh '+IP1+' '+GW1+' '+IP2+' '+GW2, function(error, stdout, stderr) { + res.send({commands: commands, instructions: instructions}); + }); + }); +} + +function runCommand(req, res, next){ + //Removing the out of bounds error + if(req.body.command == ''){req.body.command = ' '} + exec(req.body.command, function(error, stdout, stderr) { + if(stderr){res.send(stderr)} + else if(stdout){res.send(stdout)} + else{res.send(error)} + }); +} + +v1.get('/tutorials', grabTutorials); +v1.get('/file/:tutorial', grabFile); +v1.post('/command', runCommand); |