IGNITE-6920 Added direct-install build for Web Console.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/69eced65 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/69eced65 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/69eced65 Branch: refs/heads/ignite-zk Commit: 69eced65909f7ab72197e5a256c1ccde68167e7a Parents: caad1e9 Author: Andrey Novikov <anovi...@gridgain.com> Authored: Fri Nov 17 13:28:14 2017 +0700 Committer: Andrey Novikov <anovi...@gridgain.com> Committed: Fri Nov 17 13:28:14 2017 +0700 ---------------------------------------------------------------------- modules/web-console/.gitignore | 11 +- modules/web-console/DEVNOTES.txt | 13 +- modules/web-console/backend/.gitignore | 6 - modules/web-console/backend/app/apiServer.js | 76 ++-- .../web-console/backend/app/browsersHandler.js | 442 +++++++++---------- modules/web-console/backend/app/mongo.js | 73 ++- modules/web-console/backend/app/nconf.js | 44 +- modules/web-console/backend/app/routes.js | 26 +- modules/web-console/backend/app/settings.js | 84 ++-- modules/web-console/backend/index.js | 25 +- modules/web-console/backend/injector.js | 4 +- modules/web-console/backend/package.json | 22 +- .../compose/frontend/nginx/web-console.conf | 1 - .../docker/standalone/nginx/web-console.conf | 1 - modules/web-console/frontend/.gitignore | 8 +- .../generator/JavaTransformer.service.js | 2 + .../frontend/webpack/webpack.dev.babel.js | 5 +- 17 files changed, 466 insertions(+), 377 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/.gitignore ---------------------------------------------------------------------- diff --git a/modules/web-console/.gitignore b/modules/web-console/.gitignore index 9ddddc4..8648ae5 100644 --- a/modules/web-console/.gitignore +++ b/modules/web-console/.gitignore @@ -1,6 +1,5 @@ -docker/standalone/backend/build -docker/standalone/frontend/build -docker/standalone/data -docker/compose/backend/build -docker/compose/frontend/build -docker/dev/data +.npmrc +package-lock.json +build/ +node_modules/ +data/ http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/DEVNOTES.txt ---------------------------------------------------------------------- diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt index aa8702e..4ff68a7 100644 --- a/modules/web-console/DEVNOTES.txt +++ b/modules/web-console/DEVNOTES.txt @@ -1,8 +1,5 @@ -Ignite Web Console Instructions -====================================== - -How to deploy locally: - +Ignite Web Console Build Instructions +===================================== 1. Install locally MongoDB (version >=3.2.x) follow instructions from site http://docs.mongodb.org/manual/installation. 2. Install locally NodeJS (version >=6.5.x) using installer from site https://nodejs.org/en/download/current for your OS. 3. Change directory to '$IGNITE_HOME/modules/web-console/backend' and @@ -13,10 +10,10 @@ How to deploy locally: 6. Copy ignite-web-agent-<version>.zip from '$IGNITE_HOME/modules/web-console/web-agent/target' to '$IGNITE_HOME/modules/web-console/backend/agent_dists' folder. -Steps 1 - 6 should be executed once. - -How to run console in development mode: +Steps 1 - 4 should be executed once. +Ignite Web Console Run In Development Mode +========================================== 1. Configure MongoDB to run as service or in terminal change dir to $MONGO_INSTALL_DIR/server/3.2/bin and start MongoDB by executing "mongod". http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/.gitignore ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/.gitignore b/modules/web-console/backend/.gitignore index 0aa3ece..e5b9047 100644 --- a/modules/web-console/backend/.gitignore +++ b/modules/web-console/backend/.gitignore @@ -1,8 +1,2 @@ -*.idea -*.log -.npmrc -node_modules agent_dists/*.zip config/*.json -yarn.lock -package-lock.json http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/apiServer.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/apiServer.js b/modules/web-console/backend/app/apiServer.js index affb9c9..cb09750 100644 --- a/modules/web-console/backend/app/apiServer.js +++ b/modules/web-console/backend/app/apiServer.js @@ -21,48 +21,64 @@ module.exports = { implements: 'api-server', - inject: ['require(express)', 'configure', 'routes'] -}; - -module.exports.factory = function(Express, configure, routes) { - /** - * Connected agents manager. - */ - class ApiServer { + inject: ['require(fs)', 'require(path)', 'require(express)', 'settings', 'configure', 'routes'], + factory(fs, path, Express, settings, configure, routes) { /** - * @param {Server} srv + * Connected agents manager. */ - attach(srv) { - const app = new Express(); + class ApiServer { + /** + * @param {Server} srv + */ + attach(srv) { + const app = new Express(); + + configure.express(app); - configure.express(app); + routes.register(app); - routes.register(app); + if (settings.packaged) { + const staticDir = path.join(process.cwd(), 'libs/frontend'); - // Catch 404 and forward to error handler. - app.use((req, res, next) => { - const err = new Error('Not Found: ' + req.originalUrl); + try { + fs.accessSync(staticDir, fs.F_OK); - err.status = 404; + app.use('/', Express.static(staticDir)); - next(err); - }); + app.get('*', function(req, res) { + res.sendFile(path.join(staticDir, 'index.html')); + }); + } + catch (e) { + console.log(`Failed to find folder with frontend files: ${staticDir}`); + } + } - // Production error handler: no stacktraces leaked to user. - app.use((err, req, res) => { - res.status(err.status || 500); + // Catch 404 and forward to error handler. + app.use((req, res, next) => { + const err = new Error('Not Found: ' + req.originalUrl); - res.render('error', { - message: err.message, - error: {} + err.status = 404; + + next(err); }); - }); - srv.addListener('request', app); + // Production error handler: no stacktraces leaked to user. + app.use((err, req, res) => { + res.status(err.status || 500); - return app; + res.render('error', { + message: err.message, + error: {} + }); + }); + + srv.addListener('request', app); + + return app; + } } - } - return new ApiServer(); + return new ApiServer(); + } }; http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/browsersHandler.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/browsersHandler.js b/modules/web-console/backend/app/browsersHandler.js index f4ff23c..8b1385d 100644 --- a/modules/web-console/backend/app/browsersHandler.js +++ b/modules/web-console/backend/app/browsersHandler.js @@ -24,291 +24,289 @@ */ module.exports = { implements: 'browsers-handler', - inject: ['require(lodash)', 'require(socket.io)', 'configure', 'errors', 'mongo'] -}; + inject: ['require(lodash)', 'require(socket.io)', 'configure', 'errors', 'mongo'], + factory: (_, socketio, configure, errors, mongo) => { + class BrowserSockets { + constructor() { + this.sockets = new Map(); + } -module.exports.factory = (_, socketio, configure, errors, mongo) => { - class BrowserSockets { - constructor() { - this.sockets = new Map(); - } + /** + * @param {Socket} sock + */ + add(sock) { + const token = sock.request.user.token; - /** - * @param {Socket} sock - */ - add(sock) { - const token = sock.request.user.token; + if (this.sockets.has(token)) + this.sockets.get(token).push(sock); + else + this.sockets.set(token, [sock]); - if (this.sockets.has(token)) - this.sockets.get(token).push(sock); - else - this.sockets.set(token, [sock]); + return this.sockets.get(token); + } - return this.sockets.get(token); - } + /** + * @param {Socket} sock + */ + remove(sock) { + const token = sock.request.user.token; - /** - * @param {Socket} sock - */ - remove(sock) { - const token = sock.request.user.token; + const sockets = this.sockets.get(token); - const sockets = this.sockets.get(token); + _.pull(sockets, sock); - _.pull(sockets, sock); + return sockets; + } - return sockets; - } + get(token) { + if (this.sockets.has(token)) + return this.sockets.get(token); - get(token) { - if (this.sockets.has(token)) - return this.sockets.get(token); + return []; + } - return []; + demo(token) { + return _.filter(this.sockets.get(token), (sock) => sock.request._query.IgniteDemoMode === 'true'); + } } - demo(token) { - return _.filter(this.sockets.get(token), (sock) => sock.request._query.IgniteDemoMode === 'true'); - } - } + class BrowsersHandler { + /** + * @constructor + */ + constructor() { + /** + * Connected browsers. + * @type {BrowserSockets} + */ + this._browserSockets = new BrowserSockets(); + + /** + * Registered Visor task. + * @type {Map} + */ + this._visorTasks = new Map(); + } - class BrowsersHandler { - /** - * @constructor - */ - constructor() { /** - * Connected browsers. - * @type {BrowserSockets} + * @param {Error} err + * @return {{code: number, message: *}} */ - this._browserSockets = new BrowserSockets(); + errorTransformer(err) { + return { + code: err.code || 1, + message: err.message || err + }; + } /** - * Registered Visor task. - * @type {Map} + * @param {String} token + * @param {Array.<Socket>} [socks] */ - this._visorTasks = new Map(); - } + agentStats(token, socks = this._browserSockets.get(token)) { + return this._agentHnd.agents(token) + .then((agentSocks) => { + const stat = _.reduce(agentSocks, (acc, agentSock) => { + acc.count += 1; + acc.hasDemo |= _.get(agentSock, 'demo.enabled'); - /** - * @param {Error} err - * @return {{code: number, message: *}} - */ - errorTransformer(err) { - return { - code: err.code || 1, - message: err.message || err - }; - } + if (agentSock.cluster) + acc.clusters.push(agentSock.cluster); - /** - * @param {String} token - * @param {Array.<Socket>} [socks] - */ - agentStats(token, socks = this._browserSockets.get(token)) { - return this._agentHnd.agents(token) - .then((agentSocks) => { - const stat = _.reduce(agentSocks, (acc, agentSock) => { - acc.count += 1; - acc.hasDemo |= _.get(agentSock, 'demo.enabled'); - - if (agentSock.cluster) - acc.clusters.push(agentSock.cluster); - - return acc; - }, {count: 0, hasDemo: false, clusters: []}); - - stat.clusters = _.uniqWith(stat.clusters, _.isEqual); - - return stat; - }) - .catch(() => ({count: 0, hasDemo: false, clusters: []})) - .then((stat) => _.forEach(socks, (sock) => sock.emit('agents:stat', stat))); - } + return acc; + }, {count: 0, hasDemo: false, clusters: []}); - emitNotification(sock) { - sock.emit('user:notifications', this.notification); - } + stat.clusters = _.uniqWith(stat.clusters, _.isEqual); - /** - * @param {String} notification Notification message. - */ - updateNotification(notification) { - this.notification = notification; + return stat; + }) + .catch(() => ({count: 0, hasDemo: false, clusters: []})) + .then((stat) => _.forEach(socks, (sock) => sock.emit('agents:stat', stat))); + } - for (const socks of this._browserSockets.sockets.values()) { - for (const sock of socks) - this.emitNotification(sock); + emitNotification(sock) { + sock.emit('user:notifications', this.notification); } - } - executeOnAgent(token, demo, event, ...args) { - const cb = _.last(args); + /** + * @param {String} notification Notification message. + */ + updateNotification(notification) { + this.notification = notification; - return this._agentHnd.agent(token, demo) - .then((agentSock) => agentSock.emitEvent(event, ..._.dropRight(args))) - .then((res) => cb(null, res)) - .catch((err) => cb(this.errorTransformer(err))); - } + for (const socks of this._browserSockets.sockets.values()) { + for (const sock of socks) + this.emitNotification(sock); + } + } - agentListeners(sock) { - const demo = sock.request._query.IgniteDemoMode === 'true'; - const token = () => sock.request.user.token; + executeOnAgent(token, demo, event, ...args) { + const cb = _.last(args); - // Return available drivers to browser. - sock.on('schemaImport:drivers', (...args) => { - this.executeOnAgent(token(), demo, 'schemaImport:drivers', ...args); - }); + return this._agentHnd.agent(token, demo) + .then((agentSock) => agentSock.emitEvent(event, ..._.dropRight(args))) + .then((res) => cb(null, res)) + .catch((err) => cb(this.errorTransformer(err))); + } - // Return schemas from database to browser. - sock.on('schemaImport:schemas', (...args) => { - this.executeOnAgent(token(), demo, 'schemaImport:schemas', ...args); - }); + agentListeners(sock) { + const demo = sock.request._query.IgniteDemoMode === 'true'; + const token = () => sock.request.user.token; - // Return tables from database to browser. - sock.on('schemaImport:metadata', (...args) => { - this.executeOnAgent(token(), demo, 'schemaImport:metadata', ...args); - }); - } + // Return available drivers to browser. + sock.on('schemaImport:drivers', (...args) => { + this.executeOnAgent(token(), demo, 'schemaImport:drivers', ...args); + }); - /** - * @param {Promise.<AgentSocket>} agent - * @param {Boolean} demo - * @param {Object.<String, String>} params - * @return {Promise.<T>} - */ - executeOnNode(agent, demo, params) { - return agent - .then((agentSock) => agentSock.emitEvent('node:rest', {uri: 'ignite', demo, params})) - .then((res) => { - if (res.status === 0) { - if (res.zipped) - return res; - - return JSON.parse(res.data); - } - - throw new Error(res.error); + // Return schemas from database to browser. + sock.on('schemaImport:schemas', (...args) => { + this.executeOnAgent(token(), demo, 'schemaImport:schemas', ...args); }); - } - registerVisorTask(taskId, taskCls, ...argCls) { - this._visorTasks.set(taskId, { - taskCls, - argCls - }); - } + // Return tables from database to browser. + sock.on('schemaImport:metadata', (...args) => { + this.executeOnAgent(token(), demo, 'schemaImport:metadata', ...args); + }); + } - nodeListeners(sock) { - // Return command result from grid to browser. - sock.on('node:rest', (clusterId, params, cb) => { - const demo = sock.request._query.IgniteDemoMode === 'true'; - const token = sock.request.user.token; + /** + * @param {Promise.<AgentSocket>} agent + * @param {Boolean} demo + * @param {Object.<String, String>} params + * @return {Promise.<T>} + */ + executeOnNode(agent, demo, params) { + return agent.then((agentSock) => agentSock.emitEvent('node:rest', {uri: 'ignite', demo, params})) + .then((res) => { + if (res.status === 0) { + if (res.zipped) + return res; - const agent = this._agentHnd.agent(token, demo, clusterId); + return JSON.parse(res.data); + } - this.executeOnNode(agent, demo, params) - .then((data) => cb(null, data)) - .catch((err) => cb(this.errorTransformer(err))); - }); + throw new Error(res.error); + }); + } - const internalVisor = (postfix) => `org.apache.ignite.internal.visor.${postfix}`; + registerVisorTask(taskId, taskCls, ...argCls) { + this._visorTasks.set(taskId, { + taskCls, + argCls + }); + } - this.registerVisorTask('querySql', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArg')); - this.registerVisorTask('querySqlV2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV2')); - this.registerVisorTask('querySqlV3', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV3')); - this.registerVisorTask('querySqlX2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryTaskArg')); + nodeListeners(sock) { + // Return command result from grid to browser. + sock.on('node:rest', (clusterId, params, cb) => { + const demo = sock.request._query.IgniteDemoMode === 'true'; + const token = sock.request.user.token; - this.registerVisorTask('queryScanX2', internalVisor('query.VisorScanQueryTask'), internalVisor('query.VisorScanQueryTaskArg')); + const agent = this._agentHnd.agent(token, demo, clusterId); - this.registerVisorTask('queryFetch', internalVisor('query.VisorQueryNextPageTask'), 'org.apache.ignite.lang.IgniteBiTuple', 'java.lang.String', 'java.lang.Integer'); - this.registerVisorTask('queryFetchX2', internalVisor('query.VisorQueryNextPageTask'), internalVisor('query.VisorQueryNextPageTaskArg')); + this.executeOnNode(agent, demo, params) + .then((data) => cb(null, data)) + .catch((err) => cb(this.errorTransformer(err))); + }); - this.registerVisorTask('queryClose', internalVisor('query.VisorQueryCleanupTask'), 'java.util.Map', 'java.util.UUID', 'java.util.Set'); - this.registerVisorTask('queryCloseX2', internalVisor('query.VisorQueryCleanupTask'), internalVisor('query.VisorQueryCleanupTaskArg')); + const internalVisor = (postfix) => `org.apache.ignite.internal.visor.${postfix}`; + this.registerVisorTask('querySql', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArg')); + this.registerVisorTask('querySqlV2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV2')); + this.registerVisorTask('querySqlV3', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV3')); + this.registerVisorTask('querySqlX2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryTaskArg')); - // Return command result from grid to browser. - sock.on('node:visor', (clusterId, taskId, nids, ...args) => { - const demo = sock.request._query.IgniteDemoMode === 'true'; - const token = sock.request.user.token; + this.registerVisorTask('queryScanX2', internalVisor('query.VisorScanQueryTask'), internalVisor('query.VisorScanQueryTaskArg')); - const cb = _.last(args); - args = _.dropRight(args); + this.registerVisorTask('queryFetch', internalVisor('query.VisorQueryNextPageTask'), 'org.apache.ignite.lang.IgniteBiTuple', 'java.lang.String', 'java.lang.Integer'); + this.registerVisorTask('queryFetchX2', internalVisor('query.VisorQueryNextPageTask'), internalVisor('query.VisorQueryNextPageTaskArg')); - const desc = this._visorTasks.get(taskId); + this.registerVisorTask('queryClose', internalVisor('query.VisorQueryCleanupTask'), 'java.util.Map', 'java.util.UUID', 'java.util.Set'); + this.registerVisorTask('queryCloseX2', internalVisor('query.VisorQueryCleanupTask'), internalVisor('query.VisorQueryCleanupTaskArg')); - if (_.isNil(desc)) - return cb(this.errorTransformer(new errors.IllegalArgumentException(`Failed to find Visor task for id: ${taskId}`))); - const params = { - cmd: 'exe', - name: 'org.apache.ignite.internal.visor.compute.VisorGatewayTask', - p1: nids, - p2: desc.taskCls - }; + // Return command result from grid to browser. + sock.on('node:visor', (clusterId, taskId, nids, ...args) => { + const demo = sock.request._query.IgniteDemoMode === 'true'; + const token = sock.request.user.token; - _.forEach(_.concat(desc.argCls, args), (param, idx) => { params[`p${idx + 3}`] = param; }); + const cb = _.last(args); + args = _.dropRight(args); - const agent = this._agentHnd.agent(token, demo, clusterId); + const desc = this._visorTasks.get(taskId); - this.executeOnNode(agent, demo, params) - .then((data) => { - if (data.zipped) - return cb(null, data); + if (_.isNil(desc)) + return cb(this.errorTransformer(new errors.IllegalArgumentException(`Failed to find Visor task for id: ${taskId}`))); - if (data.finished) - return cb(null, data.result); + const params = { + cmd: 'exe', + name: 'org.apache.ignite.internal.visor.compute.VisorGatewayTask', + p1: nids, + p2: desc.taskCls + }; - cb(this.errorTransformer(data.error)); - }) - .catch((err) => cb(this.errorTransformer(err))); - }); - } + _.forEach(_.concat(desc.argCls, args), (param, idx) => { params[`p${idx + 3}`] = param; }); - /** - * - * @param server - * @param {AgentsHandler} agentHnd - */ - attach(server, agentHnd) { - this._agentHnd = agentHnd; + const agent = this._agentHnd.agent(token, demo, clusterId); - if (this.io) - throw 'Browser server already started!'; + this.executeOnNode(agent, demo, params) + .then((data) => { + if (data.zipped) + return cb(null, data); - mongo.Notifications.findOne().sort('-date').exec() - .then((notification) => { - this.notification = notification; - }) - .then(() => { - const io = socketio(server); + if (data.finished) + return cb(null, data.result); - configure.socketio(io); + cb(this.errorTransformer(data.error)); + }) + .catch((err) => cb(this.errorTransformer(err))); + }); + } - // Handle browser connect event. - io.sockets.on('connection', (sock) => { - this._browserSockets.add(sock); + /** + * + * @param server + * @param {AgentsHandler} agentHnd + */ + attach(server, agentHnd) { + this._agentHnd = agentHnd; - // Handle browser disconnect event. - sock.on('disconnect', () => { - this._browserSockets.remove(sock); + if (this.io) + throw 'Browser server already started!'; - const demo = sock.request._query.IgniteDemoMode === 'true'; + mongo.Notifications.findOne().sort('-date').exec() + .then((notification) => { + this.notification = notification; + }) + .then(() => { + const io = socketio(server); - // Stop demo if latest demo tab for this token. - demo && agentHnd.tryStopDemo(sock); - }); + configure.socketio(io); - this.agentListeners(sock); - this.nodeListeners(sock); + // Handle browser connect event. + io.sockets.on('connection', (sock) => { + this._browserSockets.add(sock); - this.agentStats(sock.request.user.token, [sock]); - this.emitNotification(sock); + // Handle browser disconnect event. + sock.on('disconnect', () => { + this._browserSockets.remove(sock); + + const demo = sock.request._query.IgniteDemoMode === 'true'; + + // Stop demo if latest demo tab for this token. + demo && agentHnd.tryStopDemo(sock); + }); + + this.agentListeners(sock); + this.nodeListeners(sock); + + this.agentStats(sock.request.user.token, [sock]); + this.emitNotification(sock); + }); }); - }); + } } - } - return new BrowsersHandler(); + return new BrowsersHandler(); + } }; http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/mongo.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/mongo.js b/modules/web-console/backend/app/mongo.js index 7043fcd..81076af 100644 --- a/modules/web-console/backend/app/mongo.js +++ b/modules/web-console/backend/app/mongo.js @@ -24,16 +24,10 @@ */ module.exports = { implements: 'mongo', - inject: ['require(passport-local-mongoose)', 'settings', 'ignite_modules/mongo:*', 'mongoose'] + inject: ['require(passport-local-mongoose)', 'settings', 'mongoose'] }; -module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose) { - // Use native promises - mongoose.Promise = global.Promise; - - // Connect to mongoDB database. - mongoose.connect(settings.mongoUrl, {server: {poolSize: 4}}); - +const defineSchema = (passportMongo, mongoose) => { const Schema = mongoose.Schema; const ObjectId = mongoose.Schema.Types.ObjectId; const result = { connection: mongoose.connection }; @@ -1147,12 +1141,6 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose // Define Notifications model. result.Notifications = mongoose.model('Notifications', NotificationsSchema); - // Registering the routes of all plugin modules - for (const name in pluginMongo) { - if (pluginMongo.hasOwnProperty(name)) - pluginMongo[name].register(mongoose, result); - } - result.handleError = function(res, err) { // TODO IGNITE-843 Send error to admin res.status(err.code || 500).send(err.message); @@ -1160,3 +1148,60 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose return result; }; + +module.exports.factory = function(passportMongo, settings, mongoose) { + // Use native promises + mongoose.Promise = global.Promise; + + console.log('Trying to connect to local MongoDB...'); + + // Connect to mongoDB database. + return mongoose.connect(settings.mongoUrl, {server: {poolSize: 4}}) + .catch(() => { + console.log('Failed to connect to local MongoDB, will try to download and start embedded MongoDB'); + + const {MongodHelper} = require('mongodb-prebuilt'); + const {MongoDBDownload} = require('mongodb-download'); + + const helper = new MongodHelper(['--port', '27017', '--dbpath', `${process.cwd()}/user_data`]); + + helper.mongoBin.mongoDBPrebuilt.mongoDBDownload = new MongoDBDownload({ + downloadDir: `${process.cwd()}/libs/mongodb`, + version: '3.4.7' + }); + + let mongodRun; + + if (settings.packaged) { + mongodRun = new Promise((resolve, reject) => { + helper.resolveLink = resolve; + helper.rejectLink = reject; + + helper.mongoBin.runCommand() + .then(() => { + helper.mongoBin.childProcess.removeAllListeners('close'); + + helper.mongoBin.childProcess.stderr.on('data', (data) => helper.stderrHandler(data)); + helper.mongoBin.childProcess.stdout.on('data', (data) => helper.stdoutHandler(data)); + helper.mongoBin.childProcess.on('close', (code) => helper.closeHandler(code)); + }); + }); + } + else + mongodRun = helper.run(); + + return mongodRun + .catch((err) => console.log('Failed to start embedded MongoDB', err)) + .then(() => { + console.log('Embedded MongoDB successfully started'); + + return mongoose.connect(settings.mongoUrl, {server: {poolSize: 4}}); + }) + .catch((err) => { + console.log('Failed to connect to embedded MongoDB', err); + + return Promise.reject(err); + }); + }) + .then(() => defineSchema(passportMongo, mongoose)); +}; http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/nconf.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/nconf.js b/modules/web-console/backend/app/nconf.js index c585ac6..6813f0f 100644 --- a/modules/web-console/backend/app/nconf.js +++ b/modules/web-console/backend/app/nconf.js @@ -24,25 +24,29 @@ */ module.exports = { implements: 'nconf', - inject: ['require(nconf)', 'require(fs)'] -}; - -module.exports.factory = function(nconf, fs) { - const default_config = './config/settings.json'; - const file = process.env.SETTINGS || default_config; - - nconf.env({separator: '_'}); - - try { - fs.accessSync(file, fs.F_OK); - - nconf.file({file}); - } catch (ignore) { - nconf.file({file: default_config}); + inject: ['require(nconf)', 'require(fs)'], + factory(nconf, fs) { + nconf.env({separator: '_'}).argv(); + + const dfltFile = 'config/settings.json'; + const customFile = nconf.get('settings') || dfltFile; + + try { + fs.accessSync(customFile, fs.F_OK); + + nconf.file({file: customFile}); + } + catch (ignored) { + try { + fs.accessSync(dfltFile, fs.F_OK); + + nconf.file({file: dfltFile}); + } + catch (ignored2) { + // No-op. + } + } + + return nconf; } - - if (process.env.CONFIG_PATH && fs.existsSync(process.env.CONFIG_PATH)) - nconf.file({file: process.env.CONFIG_PATH}); - - return nconf; }; http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/routes.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/routes.js b/modules/web-console/backend/app/routes.js index 826407b..aa6efae 100644 --- a/modules/web-console/backend/app/routes.js +++ b/modules/web-console/backend/app/routes.js @@ -44,22 +44,22 @@ module.exports.factory = function(publicRoute, adminRoute, profilesRoute, demoRo }; // Registering the standard routes - app.use('/', publicRoute); - app.use('/admin', _mustAuthenticated, _adminOnly, adminRoute); - app.use('/profile', _mustAuthenticated, profilesRoute); - app.use('/demo', _mustAuthenticated, demoRoute); + app.use('/api/v1/', publicRoute); + app.use('/api/v1/admin', _mustAuthenticated, _adminOnly, adminRoute); + app.use('/api/v1/profile', _mustAuthenticated, profilesRoute); + app.use('/api/v1/demo', _mustAuthenticated, demoRoute); - app.all('/configuration/*', _mustAuthenticated); + app.all('/api/v1/configuration/*', _mustAuthenticated); - app.use('/configuration', configurationsRoute); - app.use('/configuration/clusters', clustersRoute); - app.use('/configuration/domains', domainsRoute); - app.use('/configuration/caches', cachesRoute); - app.use('/configuration/igfs', igfssRoute); + app.use('/api/v1/configuration', configurationsRoute); + app.use('/api/v1/configuration/clusters', clustersRoute); + app.use('/api/v1/configuration/domains', domainsRoute); + app.use('/api/v1/configuration/caches', cachesRoute); + app.use('/api/v1/configuration/igfs', igfssRoute); - app.use('/notebooks', _mustAuthenticated, notebooksRoute); - app.use('/downloads', _mustAuthenticated, downloadsRoute); - app.use('/activities', _mustAuthenticated, activitiesRoute); + app.use('/api/v1/notebooks', _mustAuthenticated, notebooksRoute); + app.use('/api/v1/downloads', _mustAuthenticated, downloadsRoute); + app.use('/api/v1/activities', _mustAuthenticated, activitiesRoute); } }; }; http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/settings.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/settings.js b/modules/web-console/backend/app/settings.js index 05cb7f6..5032443 100644 --- a/modules/web-console/backend/app/settings.js +++ b/modules/web-console/backend/app/settings.js @@ -24,50 +24,56 @@ */ module.exports = { implements: 'settings', - inject: ['nconf', 'require(fs)'] -}; + inject: ['nconf', 'require(fs)'], + factory(nconf, fs) { + /** + * Normalize a port into a number, string, or false. + */ + const _normalizePort = function(val) { + const port = parseInt(val, 10); + + // named pipe + if (isNaN(port)) + return val; -module.exports.factory = function(nconf, fs) { - /** - * Normalize a port into a number, string, or false. - */ - const _normalizePort = function(val) { - const port = parseInt(val, 10); + // port number + if (port >= 0) + return port; - // named pipe - if (isNaN(port)) - return val; + return false; + }; - // port number - if (port >= 0) - return port; + const mail = nconf.get('mail') || {}; - return false; - }; + mail.address = (username, email) => username ? '"' + username + '" <' + email + '>' : email; - const mail = nconf.get('mail') || {}; + const packaged = __dirname.startsWith('/snapshot/') || __dirname.startsWith('C:\\snapshot\\'); - mail.address = (username, email) => username ? '"' + username + '" <' + email + '>' : email; + const dfltAgentDists = packaged ? 'libs/agent_dists' : 'agent_dists'; + const dfltHost = packaged ? '0.0.0.0' : '127.0.0.1'; + const dfltPort = packaged ? 80 : 3000; - return { - agent: { - dists: 'agent_dists' - }, - server: { - host: nconf.get('server:host') || '127.0.0.1', - port: _normalizePort(nconf.get('server:port') || 3000), - SSLOptions: nconf.get('server:ssl') && { - enable301Redirects: true, - trustXFPHeader: true, - key: fs.readFileSync(nconf.get('server:key')), - cert: fs.readFileSync(nconf.get('server:cert')), - passphrase: nconf.get('server:keyPassphrase') - } - }, - mail, - mongoUrl: nconf.get('mongodb:url') || 'mongodb://127.0.0.1/console', - cookieTTL: 3600000 * 24 * 30, - sessionSecret: nconf.get('server:sessionSecret') || 'keyboard cat', - tokenLength: 20 - }; + return { + agent: { + dists: nconf.get('agent:dists') || dfltAgentDists + }, + packaged, + server: { + host: nconf.get('server:host') || dfltHost, + port: _normalizePort(nconf.get('server:port') || dfltPort), + SSLOptions: nconf.get('server:ssl') && { + enable301Redirects: true, + trustXFPHeader: true, + key: fs.readFileSync(nconf.get('server:key')), + cert: fs.readFileSync(nconf.get('server:cert')), + passphrase: nconf.get('server:keyPassphrase') + } + }, + mail, + mongoUrl: nconf.get('mongodb:url') || 'mongodb://127.0.0.1/console', + cookieTTL: 3600000 * 24 * 30, + sessionSecret: nconf.get('server:sessionSecret') || 'keyboard cat', + tokenLength: 20 + }; + } }; http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/index.js b/modules/web-console/backend/index.js index 8454789..266fa54 100644 --- a/modules/web-console/backend/index.js +++ b/modules/web-console/backend/index.js @@ -17,14 +17,21 @@ 'use strict'; -const _ = require('lodash'); const fs = require('fs'); const path = require('path'); + +require('app-module-path').addPath(path.join(__dirname, 'node_modules')); + +const _ = require('lodash'); +const getos = require('getos'); const http = require('http'); const https = require('https'); const MigrateMongoose = require('migrate-mongoose'); -const igniteModules = process.env.IGNITE_MODULES ? + +const packaged = __dirname.startsWith('/snapshot/') || __dirname.startsWith('C:\\snapshot\\'); + +const igniteModules = !packaged && process.env.IGNITE_MODULES ? path.join(path.normalize(process.env.IGNITE_MODULES), 'backend') : path.join(__dirname, 'ignite_modules'); let injector; @@ -34,6 +41,8 @@ try { fs.accessSync(igniteModulesInjector, fs.F_OK); + process.env.NODE_PATH = path.join(__dirname, 'node_modules'); + injector = require(igniteModulesInjector); } catch (ignore) { @@ -93,7 +102,7 @@ const init = ([settings, apiSrv, agentsHnd, browsersHnd]) => { /** * Run mongo model migration. - * + * * @param dbConnectionUri Mongo connection url. * @param group Migrations group. * @param migrationsPath Migrations path. @@ -122,6 +131,16 @@ const migrate = (dbConnectionUri, group, migrationsPath) => { }); }; +getos(function(e, os) { + if (e) + return console.log(e); + + console.log('Your OS is: ' + JSON.stringify(os)); +}); + +injector.log.info = () => {}; +injector.log.debug = () => {}; + Promise.all([injector('settings'), injector('mongo')]) .then(([{mongoUrl}]) => { return migrate(mongoUrl, 'Ignite', path.join(__dirname, 'migrations')) http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/injector.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/injector.js b/modules/web-console/backend/injector.js index a5996b3..754967f 100644 --- a/modules/web-console/backend/injector.js +++ b/modules/web-console/backend/injector.js @@ -21,10 +21,10 @@ module.exports = fireUp.newInjector({ basePath: __dirname, modules: [ './app/**/*.js', - './config/**/*.js', './errors/**/*.js', './middlewares/**/*.js', './routes/**/*.js', - './services/**/*.js' + './services/**/*.js', + './ignite_modules/**/*.js' ] }); http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/package.json ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/package.json b/modules/web-console/backend/package.json index 29aa734..f0b2b5e 100644 --- a/modules/web-console/backend/package.json +++ b/modules/web-console/backend/package.json @@ -7,7 +7,8 @@ "ci-test": "cross-env NODE_ENV=test MOCHA_REPORTER=mocha-teamcity-reporter node ./test/index.js", "test": "cross-env NODE_ENV=test CONFIG_PATH='./test/config/settings.json' node ./test/index.js", "eslint": "eslint --env node --format node_modules/eslint-friendly-formatter ./ -- --eff-by-issue", - "start": "node ./index.js" + "start": "node ./index.js", + "build": "pkg . --out-path build" }, "author": "", "contributors": [ @@ -30,7 +31,23 @@ "linux", "win32" ], + "bin": "index.js", + "pkg": { + "assets": [ + "app/*.js", + "errors/*.js", + "ignite_modules/*", + "injector.js", + "middlewares/*.js", + "migrations/*", + "node_modules/getos/logic/*.js", + "routes/*.js", + "routes/**/*.json", + "services/*.js" + ] + }, "dependencies": { + "app-module-path": "2.2.0", "body-parser": "1.17.2", "connect-mongo": "1.3.2", "cookie-parser": "1.4.3", @@ -38,9 +55,11 @@ "express-session": "1.15.4", "fire-up": "1.0.0", "glob": "7.1.2", + "getos": "3.1.0", "jszip": "3.1.3", "lodash": "4.17.4", "migrate-mongoose": "3.2.2", + "mongodb-prebuilt": "6.3.3", "mongoose": "4.11.4", "morgan": "1.8.2", "nconf": "0.8.4", @@ -59,6 +78,7 @@ "mocha": "3.4.2", "mocha-teamcity-reporter": "1.1.1", "mockgoose": "6.0.8", + "pkg": "4.2.4", "supertest": "3.0.0" } } http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/docker/compose/frontend/nginx/web-console.conf ---------------------------------------------------------------------- diff --git a/modules/web-console/docker/compose/frontend/nginx/web-console.conf b/modules/web-console/docker/compose/frontend/nginx/web-console.conf index 323826e..3f5157d 100644 --- a/modules/web-console/docker/compose/frontend/nginx/web-console.conf +++ b/modules/web-console/docker/compose/frontend/nginx/web-console.conf @@ -39,7 +39,6 @@ server { } location /api/v1 { - rewrite /api/v1/(.*) /$1 break; proxy_set_header Host $http_host; proxy_pass http://backend-api; } http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/docker/standalone/nginx/web-console.conf ---------------------------------------------------------------------- diff --git a/modules/web-console/docker/standalone/nginx/web-console.conf b/modules/web-console/docker/standalone/nginx/web-console.conf index 3d83075..6e36eed 100644 --- a/modules/web-console/docker/standalone/nginx/web-console.conf +++ b/modules/web-console/docker/standalone/nginx/web-console.conf @@ -34,7 +34,6 @@ server { } location /api/v1 { - rewrite /api/v1/(.*) /$1 break; proxy_set_header Host $http_host; proxy_pass http://backend-api; } http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/frontend/.gitignore ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/.gitignore b/modules/web-console/frontend/.gitignore index 138a2cf..4fc11f46 100644 --- a/modules/web-console/frontend/.gitignore +++ b/modules/web-console/frontend/.gitignore @@ -1,9 +1,3 @@ -*.idea -*.log *.log.* -.npmrc -build/* -node_modules public/stylesheets/*.css -yarn.lock -package-lock.json + http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js b/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js index 4e6204f..e5f4804 100644 --- a/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js +++ b/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js @@ -1654,6 +1654,8 @@ export default class IgniteJavaTransformer extends AbstractTransformer { } if ((_.nonEmpty(clientNearCaches) || demo) && shortFactoryCls) { + imports.push('org.apache.ignite.Ignite'); + sb.append(`Ignite ignite = Ignition.start(${cfgRef});`); _.forEach(clientNearCaches, (cache, idx) => { http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/frontend/webpack/webpack.dev.babel.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/webpack/webpack.dev.babel.js b/modules/web-console/frontend/webpack/webpack.dev.babel.js index 56371cda..88bf5c6 100644 --- a/modules/web-console/frontend/webpack/webpack.dev.babel.js +++ b/modules/web-console/frontend/webpack/webpack.dev.babel.js @@ -77,10 +77,7 @@ export default merge(commonCfg, { ws: true }, '/api/v1/*': { - target: `http://localhost:${backendPort}`, - pathRewrite: { - '^/api/v1': '' - } + target: `http://localhost:${backendPort}` } }, watchOptions: {