Added GUI Environment
diff --git a/xos-apps/auto-scale/gui/src/vendor/ui.bootstrap/Gruntfile.js b/xos-apps/auto-scale/gui/src/vendor/ui.bootstrap/Gruntfile.js
new file mode 100644
index 0000000..147adb4
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/ui.bootstrap/Gruntfile.js
@@ -0,0 +1,492 @@
+/* jshint node: true */
+var markdown = require('node-markdown').Markdown;
+var fs = require('fs');
+
+module.exports = function(grunt) {
+
+  grunt.loadNpmTasks('grunt-contrib-watch');
+  grunt.loadNpmTasks('grunt-contrib-concat');
+  grunt.loadNpmTasks('grunt-contrib-copy');
+  grunt.loadNpmTasks('grunt-contrib-jshint');
+  grunt.loadNpmTasks('grunt-contrib-uglify');
+  grunt.loadNpmTasks('grunt-html2js');
+  grunt.loadNpmTasks('grunt-karma');
+  grunt.loadNpmTasks('grunt-conventional-changelog');
+  grunt.loadNpmTasks('grunt-ddescribe-iit');
+
+  // Project configuration.
+  grunt.util.linefeed = '\n';
+
+  grunt.initConfig({
+    ngversion: '1.4.7',
+    bsversion: '3.1.1',
+    modules: [],//to be filled in by build task
+    pkg: grunt.file.readJSON('package.json'),
+    dist: 'dist',
+    filename: 'ui-bootstrap',
+    filenamecustom: '<%= filename %>-custom',
+    meta: {
+      modules: 'angular.module("ui.bootstrap", [<%= srcModules %>]);',
+      tplmodules: 'angular.module("ui.bootstrap.tpls", [<%= tplModules %>]);',
+      all: 'angular.module("ui.bootstrap", ["ui.bootstrap.tpls", <%= srcModules %>]);',
+      cssInclude: '',
+      cssFileBanner: '/* Include this file in your html if you are using the CSP mode. */\n\n',
+      cssFileDest: '<%= dist %>/<%= filename %>-<%= pkg.version %>-csp.css',
+      banner: ['/*',
+               ' * <%= pkg.name %>',
+               ' * <%= pkg.homepage %>\n',
+               ' * Version: <%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>',
+               ' * License: <%= pkg.license %>',
+               ' */\n'].join('\n')
+    },
+    delta: {
+      docs: {
+        files: ['misc/demo/index.html'],
+        tasks: ['after-test']
+      },
+      html: {
+        files: ['template/**/*.html'],
+        tasks: ['html2js', 'karma:watch:run']
+      },
+      js: {
+        files: ['src/**/*.js'],
+        //we don't need to jshint here, it slows down everything else
+        tasks: ['karma:watch:run']
+      }
+    },
+    concat: {
+      dist: {
+        options: {
+          banner: '<%= meta.banner %><%= meta.modules %>\n',
+          footer: '<%= meta.cssInclude %>'
+        },
+        src: [], //src filled in by build task
+        dest: '<%= dist %>/<%= filename %>-<%= pkg.version %>.js'
+      },
+      dist_tpls: {
+        options: {
+          banner: '<%= meta.banner %><%= meta.all %>\n<%= meta.tplmodules %>\n',
+          footer: '<%= meta.cssInclude %>'
+        },
+        src: [], //src filled in by build task
+        dest: '<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.js'
+      }
+    },
+    copy: {
+      demohtml: {
+        options: {
+          //process html files with gruntfile config
+          processContent: grunt.template.process
+        },
+        files: [{
+          expand: true,
+          src: ['**/*.html'],
+          cwd: 'misc/demo/',
+          dest: 'dist/'
+        }]
+      },
+      demoassets: {
+        files: [{
+          expand: true,
+          //Don't re-copy html files, we process those
+          src: ['**/**/*', '!**/*.html'],
+          cwd: 'misc/demo',
+          dest: 'dist/'
+        }]
+      }
+    },
+    uglify: {
+      options: {
+        banner: '<%= meta.banner %>'
+      },
+      dist:{
+        src:['<%= concat.dist.dest %>'],
+        dest:'<%= dist %>/<%= filename %>-<%= pkg.version %>.min.js'
+      },
+      dist_tpls:{
+        src:['<%= concat.dist_tpls.dest %>'],
+        dest:'<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.min.js'
+      }
+    },
+    html2js: {
+      dist: {
+        options: {
+          module: null, // no bundle module for all the html2js templates
+          base: '.'
+        },
+        files: [{
+          expand: true,
+          src: ['template/**/*.html'],
+          ext: '.html.js'
+        }]
+      }
+    },
+    jshint: {
+      files: ['Gruntfile.js','src/**/*.js'],
+      options: {
+        jshintrc: '.jshintrc'
+      }
+    },
+    karma: {
+      options: {
+        configFile: 'karma.conf.js'
+      },
+      watch: {
+        background: true
+      },
+      continuous: {
+        singleRun: true
+      },
+      jenkins: {
+        singleRun: true,
+        autoWatch: false,
+        colors: false,
+        reporters: ['dots', 'junit'],
+        browsers: ['Chrome', 'ChromeCanary', 'Firefox', 'Opera', '/Users/jenkins/bin/safari.sh']
+      },
+      travis: {
+        singleRun: true,
+        autoWatch: false,
+        reporters: ['dots'],
+        browsers: ['Firefox']
+      },
+      coverage: {
+        preprocessors: {
+          'src/*/*.js': 'coverage'
+        },
+        reporters: ['progress', 'coverage']
+      }
+    },
+    conventionalChangelog: {
+      options: {
+        changelogOpts: {
+          preset: 'angular'
+        },
+        templateFile: 'misc/changelog.tpl.md'
+      },
+      release: {
+        src: 'CHANGELOG.md'
+      }
+    },
+    shell: {
+      //We use %version% and evluate it at run-time, because <%= pkg.version %>
+      //is only evaluated once
+      'release-prepare': [
+        'grunt before-test after-test',
+        'grunt version', //remove "-SNAPSHOT"
+        'grunt conventionalChangelog'
+      ],
+      'release-complete': [
+        'git commit CHANGELOG.md package.json -m "chore(release): v%version%"',
+        'git tag %version%'
+      ],
+      'release-start': [
+        'grunt version:minor:"SNAPSHOT"',
+        'git commit package.json -m "chore(release): Starting v%version%"'
+      ]
+    },
+    'ddescribe-iit': {
+      files: [
+        'src/**/*.spec.js'
+      ]
+    }
+  });
+
+  //register before and after test tasks so we've don't have to change cli
+  //options on the google's CI server
+  grunt.registerTask('before-test', ['enforce', 'ddescribe-iit', 'jshint', 'html2js']);
+  grunt.registerTask('after-test', ['build', 'copy']);
+
+  //Rename our watch task to 'delta', then make actual 'watch'
+  //task build things, then start test server
+  grunt.renameTask('watch', 'delta');
+  grunt.registerTask('watch', ['before-test', 'after-test', 'karma:watch', 'delta']);
+
+  // Default task.
+  grunt.registerTask('default', ['before-test', 'test', 'after-test']);
+
+  grunt.registerTask('enforce', 'Install commit message enforce script if it doesn\'t exist', function() {
+    if (!grunt.file.exists('.git/hooks/commit-msg')) {
+      grunt.file.copy('misc/validate-commit-msg.js', '.git/hooks/commit-msg');
+      require('fs').chmodSync('.git/hooks/commit-msg', '0755');
+    }
+  });
+
+  //Common ui.bootstrap module containing all modules for src and templates
+  //findModule: Adds a given module to config
+  var foundModules = {};
+  function findModule(name) {
+    if (foundModules[name]) { return; }
+    foundModules[name] = true;
+
+    function breakup(text, separator) {
+      return text.replace(/[A-Z]/g, function (match) {
+        return separator + match;
+      });
+    }
+    function ucwords(text) {
+      return text.replace(/^([a-z])|\s+([a-z])/g, function ($1) {
+        return $1.toUpperCase();
+      });
+    }
+    function enquote(str) {
+      return '"' + str + '"';
+    }
+
+    var module = {
+      name: name,
+      moduleName: enquote('ui.bootstrap.' + name),
+      displayName: ucwords(breakup(name, ' ')),
+      srcFiles: grunt.file.expand('src/'+name+'/*.js'),
+      cssFiles: grunt.file.expand('src/'+name+'/*.css'),
+      tplFiles: grunt.file.expand('template/'+name+'/*.html'),
+      tpljsFiles: grunt.file.expand('template/'+name+'/*.html.js'),
+      tplModules: grunt.file.expand('template/'+name+'/*.html').map(enquote),
+      dependencies: dependenciesForModule(name),
+      docs: {
+        md: grunt.file.expand('src/'+name+'/docs/*.md')
+          .map(grunt.file.read).map(markdown).join('\n'),
+        js: grunt.file.expand('src/'+name+'/docs/*.js')
+          .map(grunt.file.read).join('\n'),
+        html: grunt.file.expand('src/'+name+'/docs/*.html')
+          .map(grunt.file.read).join('\n')
+      }
+    };
+
+    var styles = {
+      css: [],
+      js: []
+    };
+    module.cssFiles.forEach(processCSS.bind(null, styles, true));
+    if (styles.css.length) {
+      module.css = styles.css.join('\n');
+      module.cssJs = styles.js.join('\n');
+    }
+
+    module.dependencies.forEach(findModule);
+    grunt.config('modules', grunt.config('modules').concat(module));
+  }
+
+  function dependenciesForModule(name) {
+    var deps = [];
+    grunt.file.expand('src/' + name + '/*.js')
+    .map(grunt.file.read)
+    .forEach(function(contents) {
+      //Strategy: find where module is declared,
+      //and from there get everything inside the [] and split them by comma
+      var moduleDeclIndex = contents.indexOf('angular.module(');
+      var depArrayStart = contents.indexOf('[', moduleDeclIndex);
+      var depArrayEnd = contents.indexOf(']', depArrayStart);
+      var dependencies = contents.substring(depArrayStart + 1, depArrayEnd);
+      dependencies.split(',').forEach(function(dep) {
+        if (dep.indexOf('ui.bootstrap.') > -1) {
+          var depName = dep.trim().replace('ui.bootstrap.','').replace(/['"]/g,'');
+          if (deps.indexOf(depName) < 0) {
+            deps.push(depName);
+            //Get dependencies for this new dependency
+            deps = deps.concat(dependenciesForModule(depName));
+          }
+        }
+      });
+    });
+    return deps;
+  }
+
+  grunt.registerTask('dist', 'Override dist directory', function() {
+    var dir = this.args[0];
+    if (dir) { grunt.config('dist', dir); }
+  });
+
+  grunt.registerTask('build', 'Create bootstrap build files', function() {
+    var _ = grunt.util._;
+
+    //If arguments define what modules to build, build those. Else, everything
+    if (this.args.length) {
+      this.args.forEach(findModule);
+      grunt.config('filename', grunt.config('filenamecustom'));
+    } else {
+      grunt.file.expand({
+        filter: 'isDirectory', cwd: '.'
+      }, 'src/*').forEach(function(dir) {
+        findModule(dir.split('/')[1]);
+      });
+    }
+
+    var modules = grunt.config('modules');
+    grunt.config('srcModules', _.pluck(modules, 'moduleName'));
+    grunt.config('tplModules', _.pluck(modules, 'tplModules').filter(function(tpls) { return tpls.length > 0;} ));
+    grunt.config('demoModules', modules
+      .filter(function(module) {
+        return module.docs.md && module.docs.js && module.docs.html;
+      })
+      .sort(function(a, b) {
+        if (a.name < b.name) { return -1; }
+        if (a.name > b.name) { return 1; }
+        return 0;
+      })
+    );
+
+    var cssStrings = _.flatten(_.compact(_.pluck(modules, 'css')));
+    var cssJsStrings = _.flatten(_.compact(_.pluck(modules, 'cssJs')));
+    if (cssStrings.length) {
+      grunt.config('meta.cssInclude', cssJsStrings.join('\n'));
+
+      grunt.file.write(grunt.config('meta.cssFileDest'), grunt.config('meta.cssFileBanner') +
+                       cssStrings.join('\n'));
+
+      grunt.log.writeln('File ' + grunt.config('meta.cssFileDest') + ' created');
+    }
+
+    var moduleFileMapping = _.clone(modules, true);
+    moduleFileMapping.forEach(function (module) {
+      delete module.docs;
+    });
+
+    grunt.config('moduleFileMapping', moduleFileMapping);
+
+    var srcFiles = _.pluck(modules, 'srcFiles');
+    var tpljsFiles = _.pluck(modules, 'tpljsFiles');
+    //Set the concat task to concatenate the given src modules
+    grunt.config('concat.dist.src', grunt.config('concat.dist.src')
+                 .concat(srcFiles));
+    //Set the concat-with-templates task to concat the given src & tpl modules
+    grunt.config('concat.dist_tpls.src', grunt.config('concat.dist_tpls.src')
+                 .concat(srcFiles).concat(tpljsFiles));
+
+    grunt.task.run(['concat', 'uglify', 'makeModuleMappingFile', 'makeRawFilesJs', 'makeVersionsMappingFile']);
+  });
+
+  grunt.registerTask('test', 'Run tests on singleRun karma server', function () {
+    //this task can be executed in 3 different environments: local, Travis-CI and Jenkins-CI
+    //we need to take settings for each one into account
+    if (process.env.TRAVIS) {
+      grunt.task.run('karma:travis');
+    } else {
+      var isToRunJenkinsTask = !!this.args.length;
+      if(grunt.option('coverage')) {
+        var karmaOptions = grunt.config.get('karma.options'),
+          coverageOpts = grunt.config.get('karma.coverage');
+        grunt.util._.extend(karmaOptions, coverageOpts);
+        grunt.config.set('karma.options', karmaOptions);
+      }
+      grunt.task.run(this.args.length ? 'karma:jenkins' : 'karma:continuous');
+    }
+  });
+
+  grunt.registerTask('makeModuleMappingFile', function () {
+    var _ = grunt.util._;
+    var moduleMappingJs = 'dist/assets/module-mapping.json';
+    var moduleMappings = grunt.config('moduleFileMapping');
+    var moduleMappingsMap = _.object(_.pluck(moduleMappings, 'name'), moduleMappings);
+    var jsContent = JSON.stringify(moduleMappingsMap);
+    grunt.file.write(moduleMappingJs, jsContent);
+    grunt.log.writeln('File ' + moduleMappingJs.cyan + ' created.');
+  });
+
+  grunt.registerTask('makeRawFilesJs', function () {
+    var _ = grunt.util._;
+    var jsFilename = 'dist/assets/raw-files.json';
+    var genRawFilesJs = require('./misc/raw-files-generator');
+
+    genRawFilesJs(grunt, jsFilename, _.flatten(grunt.config('concat.dist_tpls.src')),
+                  grunt.config('meta.banner'), grunt.config('meta.cssFileBanner'));
+  });
+
+  grunt.registerTask('makeVersionsMappingFile', function () {
+    var done = this.async();
+
+    var exec = require('child_process').exec;
+
+    var versionsMappingFile = 'dist/versions-mapping.json';
+
+    exec('git tag --sort -version:refname', function(error, stdout, stderr) {
+      // Let's remove the oldest 14 versions.
+      var versions = stdout.split('\n').slice(0, -14);
+      var jsContent = versions.map(function(version) {
+        return {
+          version: version,
+          url: '/bootstrap/versioned-docs/' + version
+        };
+      });
+      jsContent[0] = {
+        version: 'Current',
+        url: '/bootstrap'
+      };
+      grunt.file.write(versionsMappingFile, JSON.stringify(jsContent));
+      grunt.log.writeln('File ' + versionsMappingFile.cyan + ' created.');
+      done();
+    });
+
+  });
+
+  /**
+   * Logic from AngularJS
+   * https://github.com/angular/angular.js/blob/36831eccd1da37c089f2141a2c073a6db69f3e1d/lib/grunt/utils.js#L121-L145
+   */
+  function processCSS(state, minify, file) {
+    /* jshint quotmark: false */
+    var css = fs.readFileSync(file).toString(),
+      js;
+    state.css.push(css);
+
+    if(minify){
+      css = css
+        .replace(/\r?\n/g, '')
+        .replace(/\/\*.*?\*\//g, '')
+        .replace(/:\s+/g, ':')
+        .replace(/\s*\{\s*/g, '{')
+        .replace(/\s*\}\s*/g, '}')
+        .replace(/\s*\,\s*/g, ',')
+        .replace(/\s*\;\s*/g, ';');
+    }
+    //escape for js
+    css = css
+      .replace(/\\/g, '\\\\')
+      .replace(/'/g, "\\'")
+      .replace(/\r?\n/g, '\\n');
+    js = "!angular.$$csp() && angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>');";
+    state.js.push(js);
+
+    return state;
+  }
+
+  function setVersion(type, suffix) {
+    var file = 'package.json';
+    var VERSION_REGEX = /([\'|\"]version[\'|\"][ ]*:[ ]*[\'|\"])([\d|.]*)(-\w+)*([\'|\"])/;
+    var contents = grunt.file.read(file);
+    var version;
+    contents = contents.replace(VERSION_REGEX, function(match, left, center) {
+      version = center;
+      if (type) {
+        version = require('semver').inc(version, type);
+      }
+      //semver.inc strips our suffix if it existed
+      if (suffix) {
+        version += '-' + suffix;
+      }
+      return left + version + '"';
+    });
+    grunt.log.ok('Version set to ' + version.cyan);
+    grunt.file.write(file, contents);
+    return version;
+  }
+
+  grunt.registerTask('version', 'Set version. If no arguments, it just takes off suffix', function() {
+    setVersion(this.args[0], this.args[1]);
+  });
+
+  grunt.registerMultiTask('shell', 'run shell commands', function() {
+    var self = this;
+    var sh = require('shelljs');
+    self.data.forEach(function(cmd) {
+      cmd = cmd.replace('%version%', grunt.file.readJSON('package.json').version);
+      grunt.log.ok(cmd);
+      var result = sh.exec(cmd,{silent:true});
+      if (result.code !== 0) {
+        grunt.fatal(result.output);
+      }
+    });
+  });
+
+  return grunt;
+};