You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2016/03/28 10:47:47 UTC
[07/50] [abbrv] ignite git commit: IGNITE-2597 Refactored to
websockets.
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/controllers/sql-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/sql-controller.js b/modules/control-center-web/src/main/js/controllers/sql-controller.js
index 8336afd..dd712f8 100644
--- a/modules/control-center-web/src/main/js/controllers/sql-controller.js
+++ b/modules/control-center-web/src/main/js/controllers/sql-controller.js
@@ -17,15 +17,18 @@
// Controller for SQL notebook screen.
consoleModule.controller('sqlController', [
- '$scope', '$http', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', '$loading', '$common', '$confirm', '$agentDownload', 'QueryNotebooks', 'uiGridExporterConstants',
- function ($scope, $http, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, $loading, $common, $confirm, $agentDownload, QueryNotebooks, uiGridExporterConstants) {
+ '$scope', '$http', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', '$loading', '$common', '$confirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'QueryNotebooks', 'uiGridExporterConstants',
+ function ($scope, $http, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, $loading, $common, $confirm, IgniteAgentMonitor, IgniteChartColors, QueryNotebooks, uiGridExporterConstants) {
+
+ var stopTopology = null;
+
$scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
+ $interval.cancel(stopTopology);
+
if ($scope.notebook && $scope.notebook.paragraphs)
$scope.notebook.paragraphs.forEach(function (paragraph) {
_tryStopRefresh(paragraph);
});
-
- $agentDownload.stopAwaitAgent();
});
$scope.joinTip = $common.joinTip;
@@ -84,17 +87,12 @@ consoleModule.controller('sqlController', [
// We need max 1800 items to hold history for 30 mins in case of refresh every second.
var HISTORY_LENGTH = 1800;
- var CHART_COLORS = [
- '#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf',
- '#ffbb78', '#98df8a', '#ff9896', '#c5b0d5', '#aec7e8', '#c49c94', '#f7b6d2', '#c7c7c7', '#dbdb8d', '#9edae5'
- ];
-
- var MAX_VAL_COLS = CHART_COLORS.length;
+ var MAX_VAL_COLS = IgniteChartColors.length;
$anchorScroll.yOffset = 55;
$scope.chartColor = function(index) {
- return {"color": "white", "background-color": CHART_COLORS[index]};
+ return {"color": "white", "background-color": IgniteChartColors[index]};
};
$scope.chartRemoveKeyColumn = function (paragraph, index) {
@@ -256,6 +254,23 @@ consoleModule.controller('sqlController', [
});
};
+ var _refreshFn = function() {
+ IgniteAgentMonitor.topology($scope.demo)
+ .then(function(clusters) {
+ var caches = _.flattenDeep(clusters.map(function (cluster) { return cluster._caches; }));
+
+ $scope.caches = _.sortBy(_.uniq(_.reject(caches, { mode: 'LOCAL' }), function (cache) {
+ return _mask(cache.name);
+ }), 'name');
+
+ _setActiveCache();
+ })
+ .catch(_handleException)
+ .finally(function() {
+ $loading.finish('loading');
+ });
+ };
+
var loadNotebook = function (notebook) {
$scope.notebook = notebook;
@@ -278,14 +293,28 @@ consoleModule.controller('sqlController', [
else
$scope.rebuildScrollParagraphs();
- $agentDownload.startTopologyListening(getTopology, _onConnect, $scope.demo);
- };
+ IgniteAgentMonitor.startWatch({
+ state: 'base.configuration.clusters',
+ text: 'Back to Configuration',
+ goal: 'execute sql statements'
+ }, function () {
+ $state.go('base.sql.demo');
+ })
+ .then(function () {
+ $loading.start('loading');
- $loading.start('loading');
+ _refreshFn();
+
+ if ($scope.demo)
+ _.forEach($scope.notebook.paragraphs, $scope.execute);
+
+ stopTopology = $interval(_refreshFn, 5000, 0, false);
+ });
+ };
QueryNotebooks.read($scope.demo, $state.params.noteId)
.then(loadNotebook)
- .catch(function(err) {
+ .catch(function() {
$scope.notebookLoadFailed = true;
$loading.finish('loading');
@@ -329,9 +358,7 @@ consoleModule.controller('sqlController', [
else
$state.go('base.configuration.clusters');
})
- .catch(function (errMsg) {
- $common.showError(errMsg);
- });
+ .catch(_handleException);
};
$scope.renameParagraph = function (paragraph, newName) {
@@ -441,27 +468,6 @@ consoleModule.controller('sqlController', [
return panel_idx >= 0;
};
- function getTopology(clusters, onSuccess) {
- onSuccess();
-
- var caches = _.flattenDeep(clusters.map(function (cluster) { return cluster._caches; }));
-
- $scope.caches = _.sortBy(_.uniq(_.reject(caches, { mode: 'LOCAL' }), function (cache) {
- return _mask(cache.name);
- }), 'name');
-
- _setActiveCache();
-
- $loading.finish('loading');
- }
-
- function _onConnect() {
- if (!$scope.demo)
- return;
-
- _.forEach($scope.notebook.paragraphs, $scope.execute);
- }
-
var _columnFilter = function(paragraph) {
return paragraph.disabledSystemColumns || paragraph.systemColumns ? _allColumn : _hideColumn;
};
@@ -579,116 +585,113 @@ consoleModule.controller('sqlController', [
return retainedCols;
}
- var _tryCloseQueryResult = function (queryId) {
- if (queryId)
- $http.post('/api/v1/agent/query/close', { demo: $scope.demo, queryId: queryId });
- };
-
- var _processQueryResult = function (paragraph, refreshMode) {
- return function (res) {
- var prevKeyCols = paragraph.chartKeyCols;
- var prevValCols = paragraph.chartValCols;
+ var _processQueryResult = function (paragraph, res) {
+ var prevKeyCols = paragraph.chartKeyCols;
+ var prevValCols = paragraph.chartValCols;
- if (res.meta && !refreshMode) {
- paragraph.meta = [];
+ if (!_.eq(paragraph.meta, res.meta)) {
+ paragraph.meta = [];
- paragraph.chartColumns = [];
+ paragraph.chartColumns = [];
- if (!$common.isDefined(paragraph.chartKeyCols))
- paragraph.chartKeyCols = [];
+ if (!$common.isDefined(paragraph.chartKeyCols))
+ paragraph.chartKeyCols = [];
- if (!$common.isDefined(paragraph.chartValCols))
- paragraph.chartValCols = [];
+ if (!$common.isDefined(paragraph.chartValCols))
+ paragraph.chartValCols = [];
- if (res.meta.length <= 2) {
- var _key = _.find(res.meta, {fieldName: '_KEY'});
- var _val = _.find(res.meta, {fieldName: '_VAL'});
+ if (res.meta.length <= 2) {
+ var _key = _.find(res.meta, {fieldName: '_KEY'});
+ var _val = _.find(res.meta, {fieldName: '_VAL'});
- paragraph.disabledSystemColumns = (res.meta.length == 2 && _key && _val) ||
- (res.meta.length == 1 && (_key || _val));
- }
+ paragraph.disabledSystemColumns = (res.meta.length == 2 && _key && _val) ||
+ (res.meta.length == 1 && (_key || _val));
+ }
- paragraph.columnFilter = _columnFilter(paragraph);
+ paragraph.columnFilter = _columnFilter(paragraph);
- paragraph.meta = res.meta;
+ paragraph.meta = res.meta;
- _rebuildColumns(paragraph);
- }
+ _rebuildColumns(paragraph);
+ }
- paragraph.page = 1;
+ paragraph.page = 1;
- paragraph.total = 0;
+ paragraph.total = 0;
- paragraph.queryId = res.queryId;
+ paragraph.queryId = res.queryId;
- delete paragraph.errMsg;
+ delete paragraph.errMsg;
- // Prepare explain results for display in table.
- if (paragraph.queryArgs.type == "EXPLAIN" && res.rows) {
- paragraph.rows = [];
+ // Prepare explain results for display in table.
+ if (paragraph.queryArgs.type == "EXPLAIN" && res.rows) {
+ paragraph.rows = [];
- res.rows.forEach(function (row, i) {
- var line = res.rows.length - 1 == i ? row[0] : row[0] + '\n';
+ res.rows.forEach(function (row, i) {
+ var line = res.rows.length - 1 == i ? row[0] : row[0] + '\n';
- line.replace(/\"/g, '').split('\n').forEach(function (line) {
- paragraph.rows.push([line]);
- });
+ line.replace(/\"/g, '').split('\n').forEach(function (line) {
+ paragraph.rows.push([line]);
});
- }
- else
- paragraph.rows = res.rows;
-
- paragraph.gridOptions.setRows(paragraph.rows);
+ });
+ }
+ else
+ paragraph.rows = res.rows;
- var chartHistory = paragraph.chartHistory;
+ paragraph.gridOptions.setRows(paragraph.rows);
- // Clear history on query change.
- var queryChanged = paragraph.prevQuery != paragraph.query;
+ var chartHistory = paragraph.chartHistory;
- if (queryChanged) {
- paragraph.prevQuery = paragraph.query;
+ // Clear history on query change.
+ var queryChanged = paragraph.prevQuery != paragraph.query;
- chartHistory.length = 0;
+ if (queryChanged) {
+ paragraph.prevQuery = paragraph.query;
- _.forEach(paragraph.charts, function (chart) {
- chart.data.length = 0;
- })
- }
+ chartHistory.length = 0;
- // Add results to history.
- chartHistory.push({tm: new Date(), rows: paragraph.rows});
+ _.forEach(paragraph.charts, function (chart) {
+ chart.data.length = 0;
+ })
+ }
- // Keep history size no more than max length.
- while (chartHistory.length > HISTORY_LENGTH)
- chartHistory.shift();
+ // Add results to history.
+ chartHistory.push({tm: new Date(), rows: paragraph.rows});
- _showLoading(paragraph, false);
+ // Keep history size no more than max length.
+ while (chartHistory.length > HISTORY_LENGTH)
+ chartHistory.shift();
- if (paragraph.result == 'none' || paragraph.queryArgs.type != "QUERY")
- paragraph.result = 'table';
- else if (paragraph.chart()) {
- var resetCharts = queryChanged;
+ _showLoading(paragraph, false);
- if (!resetCharts) {
- var curKeyCols = paragraph.chartKeyCols;
- var curValCols = paragraph.chartValCols;
+ if (paragraph.result == 'none' || paragraph.queryArgs.type != "QUERY")
+ paragraph.result = 'table';
+ else if (paragraph.chart()) {
+ var resetCharts = queryChanged;
- resetCharts = !prevKeyCols || !prevValCols ||
- prevKeyCols.length != curKeyCols.length ||
- prevValCols.length != curValCols.length;
- }
+ if (!resetCharts) {
+ var curKeyCols = paragraph.chartKeyCols;
+ var curValCols = paragraph.chartValCols;
- _chartApplySettings(paragraph, resetCharts);
+ resetCharts = !prevKeyCols || !prevValCols ||
+ prevKeyCols.length != curKeyCols.length ||
+ prevValCols.length != curValCols.length;
}
+
+ _chartApplySettings(paragraph, resetCharts);
}
};
var _executeRefresh = function (paragraph) {
- _tryCloseQueryResult(paragraph.queryId);
-
- $http.post('/api/v1/agent/query', paragraph.queryArgs)
- .success(_processQueryResult(paragraph, true))
- .error(function (errMsg) {
+ IgniteAgentMonitor.awaitAgent()
+ .then(function () {
+ return IgniteAgentMonitor.queryClose(paragraph.queryArgs);
+ })
+ .then(function () {
+ return IgniteAgentMonitor.query(paragraph.queryArgs);
+ })
+ .then(_processQueryResult.bind(this, paragraph))
+ .catch(function (errMsg) {
paragraph.errMsg = errMsg;
});
};
@@ -705,31 +708,33 @@ consoleModule.controller('sqlController', [
_showLoading(paragraph, true);
- _tryCloseQueryResult(paragraph.queryId);
-
- paragraph.queryArgs = {
- demo: $scope.demo,
- type: "QUERY",
- query: paragraph.query,
- pageSize: paragraph.pageSize,
- cacheName: paragraph.cacheName || undefined
- };
-
- $http.post('/api/v1/agent/query', paragraph.queryArgs)
- .success(function (res) {
- _processQueryResult(paragraph)(res);
+ IgniteAgentMonitor.queryClose(paragraph.queryArgs)
+ .then(function () {
+ paragraph.queryArgs = {
+ demo: $scope.demo,
+ type: "QUERY",
+ query: paragraph.query,
+ pageSize: paragraph.pageSize,
+ cacheName: paragraph.cacheName || undefined
+ };
+
+ return IgniteAgentMonitor.query(paragraph.queryArgs);
+ })
+ .then(function (res) {
+ _processQueryResult(paragraph, res);
_tryStartRefresh(paragraph);
})
- .error(function (errMsg) {
+ .catch(function (errMsg) {
paragraph.errMsg = errMsg;
- _showLoading(paragraph, false);
+ _showLoading(paragraph, false);
$scope.stopRefresh(paragraph);
+ })
+ .finally(function () {
+ paragraph.ace.focus();
});
-
- paragraph.ace.focus();
};
$scope.queryExecuted = function(paragraph) {
@@ -744,25 +749,27 @@ consoleModule.controller('sqlController', [
_showLoading(paragraph, true);
- _tryCloseQueryResult(paragraph.queryId);
-
- paragraph.queryArgs = {
- demo: $scope.demo,
- type: "EXPLAIN",
- query: 'EXPLAIN ' + paragraph.query,
- pageSize: paragraph.pageSize,
- cacheName: paragraph.cacheName || undefined
- };
-
- $http.post('/api/v1/agent/query', paragraph.queryArgs)
- .success(_processQueryResult(paragraph))
- .error(function (errMsg) {
+ IgniteAgentMonitor.queryClose(paragraph.queryArgs)
+ .then(function () {
+ paragraph.queryArgs = {
+ demo: $scope.demo,
+ type: "EXPLAIN",
+ query: 'EXPLAIN ' + paragraph.query,
+ pageSize: paragraph.pageSize,
+ cacheName: paragraph.cacheName || undefined
+ };
+
+ return IgniteAgentMonitor.query(paragraph.queryArgs);
+ })
+ .then(_processQueryResult.bind(this, paragraph))
+ .catch(function (errMsg) {
paragraph.errMsg = errMsg;
_showLoading(paragraph, false);
+ })
+ .finally(function () {
+ paragraph.ace.focus();
});
-
- paragraph.ace.focus();
};
$scope.scan = function (paragraph) {
@@ -773,36 +780,40 @@ consoleModule.controller('sqlController', [
_showLoading(paragraph, true);
- _tryCloseQueryResult(paragraph.queryId);
-
- paragraph.queryArgs = {
- demo: $scope.demo,
- type: "SCAN",
- pageSize: paragraph.pageSize,
- cacheName: paragraph.cacheName || undefined
- };
-
- $http.post('/api/v1/agent/scan', paragraph.queryArgs)
- .success(_processQueryResult(paragraph))
- .error(function (errMsg) {
+ IgniteAgentMonitor.queryClose(paragraph.queryArgs)
+ .then(function () {
+ paragraph.queryArgs = {
+ demo: $scope.demo,
+ type: "SCAN",
+ pageSize: paragraph.pageSize,
+ cacheName: paragraph.cacheName || undefined
+ };
+
+ return IgniteAgentMonitor.query(paragraph.queryArgs);
+ })
+ .then(_processQueryResult.bind(this, paragraph))
+ .catch(function (errMsg) {
paragraph.errMsg = errMsg;
_showLoading(paragraph, false);
+ })
+ .finally(function () {
+ paragraph.ace.focus();
});
-
- paragraph.ace.focus();
};
$scope.nextPage = function(paragraph) {
_showLoading(paragraph, true);
- $http.post('/api/v1/agent/query/fetch', {
- demo: $scope.demo,
- queryId: paragraph.queryId,
- pageSize: paragraph.pageSize,
- cacheName: paragraph.queryArgs.cacheName
- })
- .success(function (res) {
+ paragraph.queryArgs = {
+ demo: $scope.demo,
+ queryId: paragraph.queryId,
+ pageSize: paragraph.pageSize,
+ cacheName: paragraph.queryArgs.cacheName
+ };
+
+ IgniteAgentMonitor.next(paragraph.queryArgs)
+ .then(function (res) {
paragraph.page++;
paragraph.total += paragraph.rows.length;
@@ -823,10 +834,13 @@ consoleModule.controller('sqlController', [
if (res.last)
delete paragraph.queryId;
})
- .error(function (errMsg) {
+ .catch(function (errMsg) {
paragraph.errMsg = errMsg;
_showLoading(paragraph, false);
+ })
+ .finally(function () {
+ paragraph.ace.focus();
});
};
@@ -887,17 +901,18 @@ consoleModule.controller('sqlController', [
paragraph.gridOptions.api.exporter.pdfExport(uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE);
};
- $scope.exportCsvAll = function(paragraph) {
- $http.post('/api/v1/agent/query/getAll', {
+ $scope.exportCsvAll = function (paragraph) {
+ IgniteAgentMonitor.query({
demo: $scope.demo,
+ type: paragraph.queryArgs.type,
query: paragraph.queryArgs.query,
cacheName: paragraph.queryArgs.cacheName
})
- .success(function (response) {
- _export(paragraph.name + '-all.csv', response.meta, response.rows);
+ .then(function (res) {
+ _export(paragraph.name + '-all.csv', res.meta, res.rows);
})
- .error(function (errMsg) {
- $common.showError(errMsg);
+ .finally(function () {
+ paragraph.ace.focus();
});
};
@@ -1337,7 +1352,7 @@ consoleModule.controller('sqlController', [
axisLabel: _yAxisLabel(paragraph),
tickFormat: _yAxisFormat
},
- color: CHART_COLORS,
+ color: IgniteChartColors,
stacked: stacked,
showControls: true
}
@@ -1405,7 +1420,7 @@ consoleModule.controller('sqlController', [
axisLabel: _yAxisLabel(paragraph),
tickFormat: _yAxisFormat
},
- color: CHART_COLORS,
+ color: IgniteChartColors,
useInteractiveGuideline: true
}
};
@@ -1426,27 +1441,27 @@ consoleModule.controller('sqlController', [
? paragraph.chartsOptions.areaChart.style
: 'stack';
- var options = {
- chart: {
- type: 'stackedAreaChart',
- height: 400,
- margin: {left: 70},
- duration: 0,
- x: _xX,
- y: _yY,
- xAxis: {
- axisLabel: _xAxisLabel(paragraph),
- tickFormat: paragraph.chartTimeLineEnabled() ? _xAxisTimeFormat : _xAxisWithLabelFormat(paragraph),
- showMaxMin: false
- },
- yAxis: {
- axisLabel: _yAxisLabel(paragraph),
- tickFormat: _yAxisFormat
- },
- color: CHART_COLORS,
- style: style
- }
- };
+ var options = {
+ chart: {
+ type: 'stackedAreaChart',
+ height: 400,
+ margin: {left: 70},
+ duration: 0,
+ x: _xX,
+ y: _yY,
+ xAxis: {
+ axisLabel: _xAxisLabel(paragraph),
+ tickFormat: paragraph.chartTimeLineEnabled() ? _xAxisTimeFormat : _xAxisWithLabelFormat(paragraph),
+ showMaxMin: false
+ },
+ yAxis: {
+ axisLabel: _yAxisLabel(paragraph),
+ tickFormat: _yAxisFormat
+ },
+ color: IgniteChartColors,
+ style: style
+ }
+ };
paragraph.charts = [{options: options, data: datum}];
@@ -1487,10 +1502,10 @@ consoleModule.controller('sqlController', [
$scope.metadata = [];
- $http.post('/api/v1/agent/cache/metadata', {demo: $scope.demo})
- .success(function (metadata) {
- $scope.metadata = _.sortBy(_.filter(metadata, function (meta) {
- var cache = _.find($scope.caches, { name: meta.cacheName });
+ IgniteAgentMonitor.metadata($scope.demo)
+ .then(function (metadata) {
+ $scope.metadata = _.sortBy(_.filter(metadata, function (meta) {
+ var cache = _.find($scope.caches, { name: meta.cacheName });
if (cache) {
meta.name = (cache.sqlSchema ? cache.sqlSchema : '"' + meta.cacheName + '"') + '.' + meta.typeName;
@@ -1503,15 +1518,12 @@ consoleModule.controller('sqlController', [
meta.children.unshift({type: 'plain', name: 'mode: ' + cache.mode});
}
- return cache;
- }), 'name');
- })
- .error(function (errMsg) {
- $common.showError(errMsg);
- })
- .finally(function() {
- $loading.finish('loadingCacheMetadata');
- });
+ return cache;
+ }), 'name');
+ })
+ .finally(function () {
+ $loading.finish('loadingCacheMetadata');
+ });
};
$scope.showResultQuery = function (paragraph) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/gulpfile.js/tasks/bundle.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/gulpfile.js/tasks/bundle.js b/modules/control-center-web/src/main/js/gulpfile.js/tasks/bundle.js
index 8d0d2e9..ce15b34 100644
--- a/modules/control-center-web/src/main/js/gulpfile.js/tasks/bundle.js
+++ b/modules/control-center-web/src/main/js/gulpfile.js/tasks/bundle.js
@@ -39,19 +39,15 @@ var options = {
minify: true
};
-gulp.task('bundle', function(cb) {
- return sequence('bundle:ignite', 'bundle:legacy', cb);
-});
+gulp.task('bundle', ['eslint', 'bundle:ignite', 'bundle:legacy']);
// Package all external dependencies and ignite-console.
-gulp.task('bundle:ignite', ['eslint'], function() {
- if (util.env.debug) {
+gulp.task('bundle:ignite', function() {
+ if (util.env.debug)
delete options.minify;
- }
- if (util.env.debug || util.env.sourcemaps) {
+ if (util.env.debug || util.env.sourcemaps)
options.sourceMaps = true;
- }
return jspm.bundleSFX('app/index', 'build/app.min.js', options);
});
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/gulpfile.js/tasks/inject-plugins.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/gulpfile.js/tasks/inject-plugins.js b/modules/control-center-web/src/main/js/gulpfile.js/tasks/inject-plugins.js
index ce5b5cd..bdac24c 100644
--- a/modules/control-center-web/src/main/js/gulpfile.js/tasks/inject-plugins.js
+++ b/modules/control-center-web/src/main/js/gulpfile.js/tasks/inject-plugins.js
@@ -23,8 +23,7 @@ var common_options = {
};
var html_targets = [
- './build/*.html',
- './build/**/*.html'
+ './build/index.html'
];
var js_targets = [
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/package.json
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/package.json b/modules/control-center-web/src/main/js/package.json
index 9766d61..02cdcd9 100644
--- a/modules/control-center-web/src/main/js/package.json
+++ b/modules/control-center-web/src/main/js/package.json
@@ -57,9 +57,10 @@
"passport": "^0.3.2",
"passport-local": "^1.0.0",
"passport-local-mongoose": "3.1.0",
+ "passport.socketio": "^3.6.1",
"require-dir": "^0.3.0",
"serve-favicon": "~2.3.0",
- "ws": "~0.8.0"
+ "socket.io": "^1.4.5"
},
"devDependencies": {
"jspm": "^0.16.15",
@@ -77,10 +78,11 @@
"angular-loading": "github:darthwade/angular-loading@^0.1.4",
"angular-motion": "github:mgcrea/angular-motion@^0.4.3",
"angular-nvd3": "github:krispo/angular-nvd3@^1.0.4",
- "angular-retina": "github:jrief/angular-retina@^0.3.8",
+ "angular-retina": "github:jrief/angular-retina@0.3.8",
"angular-sanitize": "github:angular/bower-angular-sanitize@^1.5.0",
"angular-smart-table": "github:lorenzofox3/Smart-Table@^2.1.4",
- "angular-strap": "github:akuznetsov-gridgain/angular-strap@fix-1852-2.3.6",
+ "angular-socket-io": "github:btford/angular-socket-io@^0.7.0",
+ "angular-strap": "github:mgcrea/angular-strap@2.3.7",
"angular-tree-control": "github:wix/angular-tree-control@^0.2.23",
"angular-ui-grid": "github:angular-ui/bower-ui-grid@^3.0.7",
"angular-ui-router": "github:angular-ui/ui-router@^0.2.15",
@@ -97,6 +99,7 @@
"lodash": "npm:lodash@^3.10.1",
"pdfmake": "github:bpampuch/pdfmake@^0.1.20",
"query-command-supported": "github:zenorocha/document.queryCommandSupported@^1.0.0",
+ "socket.io-client": "github:socketio/socket.io-client@1.4.5",
"text": "github:systemjs/plugin-text@^0.0.7"
},
"devDependencies": {
@@ -119,6 +122,20 @@
}
}
},
+ "github:btford/angular-socket-io@0.7.0": {
+ "dependencies": {
+ "socket.io-client": "github:socketio/socket.io-client@1.4.5"
+ }
+ },
+ "github:socketio/socket.io-client@1.4.5": {
+ "format": "global",
+ "main": "socket.io",
+ "shim": {
+ "socket.io": {
+ "exports": "io"
+ }
+ }
+ },
"github:Stuk/jszip@2.5.0": {
"format": "global",
"main": "./dist/jszip"
@@ -141,14 +158,12 @@
"github:krispo/angular-nvd3@1.0.4": {
"main": "dist/angular-nvd3",
"dependencies": {
- "angular": "^1",
"nvd3": "npm:nvd3@1.8.1",
"d3": "npm:d3@3.5.14"
},
"shim": {
"dist/angular-nvd3": {
"deps": [
- "angular",
"d3",
"nvd3"
]
@@ -218,18 +233,22 @@
"pdfmake": "github:bpampuch/pdfmake@^0.1.20"
}
},
- "github:akuznetsov-gridgain/angular-strap@fix-1852-2.3.6": {
- "main": "dist/angular-strap.tpl",
+ "github:mgcrea/angular-strap@2.3.7": {
+ "directories": {
+ "lib": "dist"
+ },
+ "main": "angular-strap.tpl",
"dependencies": {
- "angular": "github:angular/bower-angular@^1.5.0",
+ "angular": "^1",
"angular-animate": "github:angular/bower-angular-animate@^1.5.0",
"angular-motion": "github:mgcrea/angular-motion@^0.4.3",
"angular-sanitize": "github:angular/bower-angular-sanitize@^1.5.0"
},
"shim": {
- "dist/angular-strap.tpl": {
+ "angular-strap.tpl": {
"deps": [
- "./angular-strap"
+ "./angular-strap",
+ "angular"
]
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve.js b/modules/control-center-web/src/main/js/serve.js
index 59ea9e8..74342a9 100644
--- a/modules/control-center-web/src/main/js/serve.js
+++ b/modules/control-center-web/src/main/js/serve.js
@@ -66,29 +66,23 @@ const fireUp = require('fire-up').newInjector({
]
});
-Promise.all([fireUp('settings'), fireUp('app'), fireUp('agent')])
+Promise.all([fireUp('settings'), fireUp('app'), fireUp('agent'), fireUp('io')])
.then((values) => {
- const settings = values[0], app = values[1], agent = values[2];
+ const settings = values[0];
+ const app = values[1];
+ const agent = values[2];
+ const io = values[3];
- // Create HTTP server.
- const server = http.createServer(app);
-
- app.set('port', settings.server.port);
+ // Start rest server.
+ const server = settings.server.SSLOptions
+ ? https.createServer(settings.server.SSLOptions) : http.createServer();
server.listen(settings.server.port);
server.on('error', _onError.bind(null, settings.server.port));
server.on('listening', _onListening.bind(null, server.address()));
- // Create HTTPS server if needed.
- if (settings.server.SSLOptions) {
- const httpsServer = https.createServer(settings.server.SSLOptions, app);
-
- const httpsPort = settings.server.SSLOptions.port;
-
- httpsServer.listen(httpsPort);
- httpsServer.on('error', _onError.bind(null, httpsPort));
- httpsServer.on('listening', _onListening.bind(null, httpsServer.address()));
- }
+ app.listen(server);
+ io.listen(server);
// Start agent server.
const agentServer = settings.agent.SSLOptions
@@ -104,7 +98,7 @@ Promise.all([fireUp('settings'), fireUp('app'), fireUp('agent')])
if (process.send)
process.send('running');
}).catch((err) => {
- console.error(err);
+ console.error(error);
process.exit(1);
});
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/agent.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/agent.js b/modules/control-center-web/src/main/js/serve/agent.js
index 6c54ae1..04d7ed6 100644
--- a/modules/control-center-web/src/main/js/serve/agent.js
+++ b/modules/control-center-web/src/main/js/serve/agent.js
@@ -21,10 +21,21 @@
module.exports = {
implements: 'agent',
- inject: ['require(fs)', 'require(ws)', 'require(apache-ignite)', 'mongo']
+ inject: ['require(lodash)', 'require(fs)', 'require(path)', 'require(jszip)', 'require(socket.io)', 'require(apache-ignite)', 'settings', 'mongo']
};
-module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
+/**
+ * @param _
+ * @param fs
+ * @param path
+ * @param JSZip
+ * @param socketio
+ * @param apacheIgnite
+ * @param settings
+ * @param mongo
+ * @returns {AgentManager}
+ */
+module.exports.factory = function(_, fs, path, JSZip, socketio, apacheIgnite, settings, mongo) {
/**
* Creates an instance of server for Ignite.
*/
@@ -72,37 +83,39 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
class Agent {
/**
+ * @param {socketIo.Socket} _wsSrv
* @param {AgentManager} manager
- * @param {WebSocket} _wsSrv
*/
constructor(_wsSrv, manager) {
const self = this;
this._manager = manager;
- this._wsSrv = _wsSrv;
+ /**
+ * @type {socketIo.Socket}
+ * @private
+ */
+ this._wsAgents = _wsSrv;
- this._wsSrv.on('close', () => {
+ this._wsAgents.on('disconnect', () => {
if (self._user)
- self._manager._removeClient(self._user._id, self);
- });
-
- this._wsSrv.on('message', (msgStr) => {
- const msg = JSON.parse(msgStr);
-
- self['_rmt' + msg.type](msg);
+ self._manager._removeAgent(self._user._id, self);
});
- this._reqCounter = 0;
-
- this._cbMap = {};
+ this._wsAgents.on('agent:auth', (msg, cb) => self._processAuth(msg, cb));
}
- _runCommand(method, args) {
+ /**
+ *
+ * @param event
+ * @param data
+ * @returns {Promise}
+ */
+ _exec(event, data) {
const self = this;
return new Promise((resolve, reject) =>
- self._invokeRmtMethod(method, args, (error, res) => {
+ self._emit(event, data, (error, res) => {
if (error)
return reject(error);
@@ -133,10 +146,7 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
if (headers && typeof (headers) !== 'object')
throw 'headers must be an object';
- if (!method)
- method = 'GET';
- else
- method = method.toUpperCase();
+ method = method ? method.toUpperCase() : 'GET';
if (method !== 'GET' && method !== 'POST')
throw 'Unknown HTTP method: ' + method;
@@ -145,38 +155,32 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
if (error)
return cb(error);
- const restError = restResult.error;
-
- if (restError)
- return cb(restError);
+ error = restResult.error;
- const restCode = restResult.restCode;
+ const code = restResult.code;
- if (restCode !== 200) {
- if (restCode === 401)
- return cb.call({code: restCode, message: 'Failed to authenticate on node.'});
+ if (code !== 200) {
+ if (code === 401)
+ return cb({code, message: 'Failed to authenticate on node.'});
- return cb.call({
- code: restCode,
- message: restError || 'Failed connect to node and execute REST command.'
- });
+ return cb({code, message: error || 'Failed connect to node and execute REST command.'});
}
try {
- const nodeResponse = JSON.parse(restResult.response);
+ const response = JSON.parse(restResult.data);
- if (nodeResponse.successStatus === 0)
- return cb(null, nodeResponse.response);
+ if (response.successStatus === 0)
+ return cb(null, response.response);
- switch (nodeResponse.successStatus) {
+ switch (response.successStatus) {
case 1:
- return cb({code: 500, message: nodeResponse.error});
+ return cb({code: 500, message: response.error});
case 2:
- return cb({code: 401, message: nodeResponse.error});
+ return cb({code: 401, message: response.error});
case 3:
- return cb({code: 403, message: nodeResponse.error});
+ return cb({code: 403, message: response.error});
default:
- return cb(nodeResponse.error);
+ return cb(response.error);
}
}
catch (e) {
@@ -184,14 +188,7 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
}
};
- this._invokeRmtMethod('executeRest', [uri, params, demo, method, headers, body], _cb);
- }
-
- /**
- * @param {?String} error
- */
- authResult(error) {
- return this._runCommand('authResult', [error]);
+ this._emit('node:rest', {uri, params, demo, method, headers, body}, _cb);
}
/**
@@ -202,7 +199,7 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
* @returns {Promise} Promise on list of tables (see org.apache.ignite.schema.parser.DbTable java class)
*/
metadataSchemas(driverPath, driverClass, url, info) {
- return this._runCommand('schemas', [driverPath, driverClass, url, info]);
+ return this._exec('schemaImport:schemas', {driverPath, driverClass, url, info});
}
/**
@@ -215,89 +212,74 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
* @returns {Promise} Promise on list of tables (see org.apache.ignite.schema.parser.DbTable java class)
*/
metadataTables(driverPath, driverClass, url, info, schemas, tablesOnly) {
- return this._runCommand('metadata', [driverPath, driverClass, url, info, schemas, tablesOnly]);
+ return this._exec('schemaImport:metadata', {driverPath, driverClass, url, info, schemas, tablesOnly});
}
/**
* @returns {Promise} Promise on list of jars from driver folder.
*/
availableDrivers() {
- return this._runCommand('availableDrivers', []);
+ return this._exec('schemaImport:drivers');
}
/**
* Run http request
*
- * @this {AgentServer}
- * @param {String} method Command name.
- * @param {Array} args Command params.
- * @param {Function} callback on finish
+ * @this {Agent}
+ * @param {String} event Command name.
+ * @param {Object} data Command params.
+ * @param {Function} [callback] on finish
*/
- _invokeRmtMethod(method, args, callback) {
- if (this._wsSrv.readyState !== 1) {
+ _emit(event, data, callback) {
+ if (!this._wsAgents.connected) {
if (callback)
callback('org.apache.ignite.agent.AgentException: Connection is closed');
return;
}
- const msg = {method, args};
-
- if (callback) {
- const reqId = this._reqCounter++;
-
- this._cbMap[reqId] = callback;
-
- msg.reqId = reqId;
- }
-
- this._wsSrv.send(JSON.stringify(msg));
+ this._wsAgents.emit(event, data, callback);
}
- _rmtAuthMessage(msg) {
+ /**
+ * Process auth request.
+ *
+ * @param {Object} data
+ * @param {Function} cb
+ * @private
+ */
+ _processAuth(data, cb) {
const self = this;
- fs.stat('public/agent/ignite-web-agent-1.5.0.final.zip', (errFs, stats) => {
- let relDate = 0;
-
- if (!errFs)
- relDate = stats.birthtime.getTime();
+ if (!_.isEmpty(this._manager.supportedAgents)) {
+ const ver = data.ver;
+ const bt = data.bt;
- if ((msg.relDate || 0) < relDate)
- self.authResult('You are using an older version of the agent. Please reload agent archive');
+ if (_.isEmpty(ver) || _.isEmpty(bt) || _.isEmpty(this._manager.supportedAgents[ver]) ||
+ this._manager.supportedAgents[ver].buildTime > bt)
+ return cb('You are using an older version of the agent. Please reload agent archive');
+ }
- mongo.Account.findOne({token: msg.token}, (err, account) => {
- // TODO IGNITE-1379 send error to web master.
- if (err)
- self.authResult('Failed to authorize user');
- else if (!account)
- self.authResult('Invalid token, user not found');
- else {
- self.authResult(null);
+ mongo.Account.findOne({token: data.token}, (err, account) => {
+ // TODO IGNITE-1379 send error to web master.
+ if (err)
+ cb('Failed to authorize user');
+ else if (!account)
+ cb('Invalid token, user not found');
+ else {
+ self._user = account;
- self._user = account;
+ self._manager._addAgent(account._id, self);
- self._manager._addAgent(account._id, self);
+ self._cluster = new apacheIgnite.Ignite(new AgentServer(self));
- self._cluster = new apacheIgnite.Ignite(new AgentServer(self));
+ self._demo = new apacheIgnite.Ignite(new AgentServer(self, true));
- self._demo = new apacheIgnite.Ignite(new AgentServer(self, true));
- }
- });
+ cb();
+ }
});
}
- _rmtCallRes(msg) {
- const callback = this._cbMap[msg.reqId];
-
- if (!callback)
- return;
-
- delete this._cbMap[msg.reqId];
-
- callback(msg.error, msg.response);
- }
-
/**
* @returns {Ignite}
*/
@@ -311,11 +293,79 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
* @constructor
*/
constructor() {
+ /**
+ * @type {Object.<ObjectId, Array.<Agent>>}
+ */
this._agents = {};
+
+ /**
+ * @type {Object.<ObjectId, Array.<Socket>>}
+ */
+ this._users = {};
+
+ const agentArchives = fs.readdirSync(settings.agent.dists)
+ .filter((file) => path.extname(file) === '.zip');
+
+ /**
+ * @type {Object.<String, String>}
+ */
+ this.supportedAgents = {};
+
+ const jarFilter = (file) => path.extname(file) === '.jar';
+
+ for (const archive of agentArchives) {
+ const filePath = path.join(settings.agent.dists, archive);
+
+ const zip = new JSZip(fs.readFileSync(filePath));
+
+ const jarPath = _.find(_.keys(zip.files), jarFilter);
+
+ const jar = new JSZip(zip.files[jarPath].asNodeBuffer());
+
+ const manifest = jar.files['META-INF/MANIFEST.MF']
+ .asText()
+ .trim()
+ .split(/\s*\n+\s*/)
+ .map((line, r) => {
+ r = line.split(/\s*:\s*/);
+
+ this[r[0]] = r[1];
+
+ return this;
+ }, {})[0];
+
+ const ver = manifest['Implementation-Version'];
+
+ if (ver) {
+ this.supportedAgents[ver] = {
+ fileName: archive,
+ filePath,
+ buildTime: manifest['Build-Time']
+ };
+ }
+ }
+
+ const latest = _.first(Object.keys(this.supportedAgents).sort((a, b) => {
+ const aParts = a.split('.');
+ const bParts = b.split('.');
+
+ for (let i = 0; i < aParts.length; ++i) {
+ if (bParts.length === i)
+ return 1;
+
+ if (aParts[i] === aParts[i])
+ continue;
+
+ return aParts[i] > bParts[i] ? 1 : -1;
+ }
+ }));
+
+ if (latest)
+ this.supportedAgents.latest = this.supportedAgents[latest];
}
/**
- *
+ * @param {http.Server|https.Server} srv
*/
listen(srv) {
if (this._server)
@@ -323,58 +373,106 @@ module.exports.factory = function(fs, ws, apacheIgnite, mongo) {
this._server = srv;
- this._wsSrv = new ws.Server({server: this._server});
+ /**
+ * @type {WebSocketServer}
+ */
+ this._wsAgents = socketio(this._server);
const self = this;
- this._wsSrv.on('connection', (_wsSrv) => new Agent(_wsSrv, self));
+ this._wsAgents.on('connection', (_wsSrv) => new Agent(_wsSrv, self));
}
/**
- * @param userId
- * @param {Agent} client
+ * @param {ObjectId} userId
+ * @param {Socket} user
+ * @returns {int} connected agent count.
*/
- _removeClient(userId, client) {
+ addAgentListener(userId, user) {
+ let users = this._users[userId];
+
+ if (!users)
+ this._users[userId] = users = [];
+
+ users.push(user);
+
const agents = this._agents[userId];
- if (agents) {
- let idx;
+ return agents ? agents.length : 0;
+ }
- while ((idx = agents.indexOf(client)) !== -1)
- agents.splice(idx, 1);
+ /**
+ * @param {ObjectId} userId
+ * @param {Socket} user
+ * @returns {int} connected agent count.
+ */
+ removeAgentListener(userId, user) {
+ const users = this._users[userId];
- if (agents.length === 0)
- delete this._agents[userId];
- }
+ _.remove(users, (_user) => _user === user);
}
/**
* @param {ObjectId} userId
- * @param {Agent} agent
+ * @returns {Promise.<Agent>}
*/
- _addAgent(userId, agent) {
- let agents = this._agents[userId];
+ findAgent(userId) {
+ if (!this._server)
+ return Promise.reject('Agent server not started yet!');
- if (!agents) {
- agents = [];
+ const agents = this._agents[userId];
- this._agents[userId] = agents;
- }
+ if (!agents || agents.length === 0)
+ return Promise.reject('Failed to connect to agent');
- agents.push(agent);
+ return Promise.resolve(agents[0]);
}
/**
+ * Close connections for all user agents.
* @param {ObjectId} userId
- * @returns {Agent}
*/
- findClient(userId) {
+ close(userId) {
+ if (!this._server)
+ throw 'Agent server not started yet!';
+
+ const agents = this._agents[userId];
+
+ this._agents[userId] = [];
+
+ for (const agent of agents)
+ agent._emit('agent:close', 'Security token was changed for user');
+ }
+
+ /**
+ * @param userId
+ * @param {Agent} agent
+ */
+ _removeAgent(userId, agent) {
const agents = this._agents[userId];
- if (!agents || agents.length === 0)
- return null;
+ _.remove(agents, (_agent) => _agent === agent);
+
+ const users = this._users[userId];
+
+ _.forEach(users, (user) => user.emit('agent:count', {count: agents.length}));
+ }
+
+ /**
+ * @param {ObjectId} userId
+ * @param {Agent} agent
+ */
+ _addAgent(userId, agent) {
+ let agents = this._agents[userId];
+
+ if (!agents)
+ this._agents[userId] = agents = [];
+
+ agents.push(agent);
+
+ const users = this._users[userId];
- return agents[0];
+ _.forEach(users, (user) => user.emit('agent:count', {count: agents.length}));
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/agent_dists/README.txt
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/agent_dists/README.txt b/modules/control-center-web/src/main/js/serve/agent_dists/README.txt
new file mode 100644
index 0000000..d51bdf9
--- /dev/null
+++ b/modules/control-center-web/src/main/js/serve/agent_dists/README.txt
@@ -0,0 +1,7 @@
+Ignite Web Console
+======================================
+
+This is default folder for agent distributives.
+
+Also, you could specify custom folder in `serve/config/settings.json`
+
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/app.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/app.js b/modules/control-center-web/src/main/js/serve/app.js
index 5f4e4fb..e4b5eca 100644
--- a/modules/control-center-web/src/main/js/serve/app.js
+++ b/modules/control-center-web/src/main/js/serve/app.js
@@ -21,15 +21,22 @@
module.exports = {
implements: 'app',
- inject: ['require(express)', 'configure', 'routes']
+ inject: ['require(express)', 'configure', 'routes', 'io']
};
module.exports.factory = function(Express, configure, routes) {
- const app = new Express();
+ return {
+ /**
+ * @param {Server} srv
+ */
+ listen: (srv) => {
+ const app = new Express();
- configure(app);
+ configure.express(app);
- routes.register(app);
+ routes.register(app);
- return app;
+ srv.addListener('request', app);
+ }
+ };
};
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/config/default.json
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/config/default.json b/modules/control-center-web/src/main/js/serve/config/default.json
deleted file mode 100644
index 3dcc5ca..0000000
--- a/modules/control-center-web/src/main/js/serve/config/default.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "server": {
- "port": 3000,
- "https-port": 8443,
- "ssl": false,
- "key": "serve/keys/test.key",
- "cert": "serve/keys/test.crt",
- "keyPassphrase": "password"
- },
- "mongoDB": {
- "url": "mongodb://localhost/web-control-center"
- },
- "agent-server": {
- "port": 3001,
- "ssl": true,
- "key": "serve/keys/test.key",
- "cert": "serve/keys/test.crt",
- "keyPassphrase": "password"
- },
- "smtp": {
- "service": "",
- "username": "Apache Ignite Web Console",
- "email": "",
- "password": ""
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/config/settings.json.sample
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/config/settings.json.sample b/modules/control-center-web/src/main/js/serve/config/settings.json.sample
new file mode 100644
index 0000000..94dd9f7
--- /dev/null
+++ b/modules/control-center-web/src/main/js/serve/config/settings.json.sample
@@ -0,0 +1,26 @@
+{
+ "server": {
+ "port": 3000,
+ "ssl": false,
+ "key": "serve/keys/test.key",
+ "cert": "serve/keys/test.crt",
+ "keyPassphrase": "password"
+ },
+ "mongoDB": {
+ "url": "mongodb://localhost/console"
+ },
+ "agent-server": {
+ "port": 3001,
+ "ssl": false,
+ "key": "serve/keys/test.key",
+ "cert": "serve/keys/test.crt",
+ "keyPassphrase": "password"
+ },
+ "smtp": {
+ "service": "",
+ "username": "Apache Ignite Web Console",
+ "sign": "Kind regards,<br>Apache Ignite Team",
+ "email": "",
+ "password": ""
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/configure.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/configure.js b/modules/control-center-web/src/main/js/serve/configure.js
index 9d8b1d3..ac27751 100644
--- a/modules/control-center-web/src/main/js/serve/configure.js
+++ b/modules/control-center-web/src/main/js/serve/configure.js
@@ -21,46 +21,60 @@
module.exports = {
implements: 'configure',
- inject: ['require(morgan)', 'require(cookie-parser)', 'require(body-parser)', 'require(express-force-ssl)',
- 'require(express-session)', 'require(connect-mongo)', 'require(passport)', 'settings', 'mongo']
+ inject: ['require(morgan)', 'require(cookie-parser)', 'require(body-parser)',
+ 'require(express-session)', 'require(connect-mongo)', 'require(passport)', 'require(passport.socketio)', 'settings', 'mongo']
};
-module.exports.factory = function(logger, cookieParser, bodyParser, forceSSL, session, connectMongo, Passport, settings, mongo) {
- return (app) => {
- app.use(logger('dev', {
- skip: (req, res) => res.statusCode < 400
- }));
+module.exports.factory = function(logger, cookieParser, bodyParser, session, connectMongo, passport, passportSocketIo, settings, mongo) {
+ const _sessionStore = new (connectMongo(session))({mongooseConnection: mongo.connection});
- app.use(cookieParser(settings.sessionSecret));
+ return {
+ express: (app) => {
+ app.use(logger('dev', {
+ skip: (req, res) => res.statusCode < 400
+ }));
- app.use(bodyParser.json({limit: '50mb'}));
- app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
+ app.use(cookieParser(settings.sessionSecret));
- const MongoStore = connectMongo(session);
+ app.use(bodyParser.json({limit: '50mb'}));
+ app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
- app.use(session({
- secret: settings.sessionSecret,
- resave: false,
- saveUninitialized: true,
- cookie: {
- expires: new Date(Date.now() + settings.cookieTTL),
- maxAge: settings.cookieTTL
- },
- store: new MongoStore({mongooseConnection: mongo.connection})
- }));
+ app.use(session({
+ secret: settings.sessionSecret,
+ resave: false,
+ saveUninitialized: true,
+ cookie: {
+ expires: new Date(Date.now() + settings.cookieTTL),
+ maxAge: settings.cookieTTL
+ },
+ store: _sessionStore
+ }));
- app.use(Passport.initialize());
- app.use(Passport.session());
+ app.use(passport.initialize());
+ app.use(passport.session());
- Passport.serializeUser(mongo.Account.serializeUser());
- Passport.deserializeUser(mongo.Account.deserializeUser());
+ passport.serializeUser(mongo.Account.serializeUser());
+ passport.deserializeUser(mongo.Account.deserializeUser());
- Passport.use(mongo.Account.createStrategy());
+ passport.use(mongo.Account.createStrategy());
+ },
+ socketio: (io) => {
+ const _onAuthorizeSuccess = (data, accept) => {
+ accept(null, true);
+ };
- if (settings.SSLOptions) {
- app.set('forceSSLOptions', settings.SSLOptions);
+ const _onAuthorizeFail = (data, message, error, accept) => {
+ accept(null, false);
+ };
- app.use(forceSSL);
+ io.use(passportSocketIo.authorize({
+ cookieParser,
+ key: 'connect.sid', // the name of the cookie where express/connect stores its session_id
+ secret: settings.sessionSecret, // the session_secret to parse the cookie
+ store: _sessionStore, // we NEED to use a sessionstore. no memorystore please
+ success: _onAuthorizeSuccess, // *optional* callback on success - read more below
+ fail: _onAuthorizeFail // *optional* callback on fail/error - read more below
+ }));
}
};
};
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/io.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/io.js b/modules/control-center-web/src/main/js/serve/io.js
new file mode 100644
index 0000000..ded00fa
--- /dev/null
+++ b/modules/control-center-web/src/main/js/serve/io.js
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+// Fire me up!
+
+module.exports = {
+ implements: 'io',
+ inject: ['require(lodash)', 'require(socket.io)', 'require(apache-ignite)', 'agent', 'configure']
+};
+
+module.exports.factory = (_, socketio, apacheIgnite, agentMgr, configure) => {
+ const SqlFieldsQuery = apacheIgnite.SqlFieldsQuery;
+ const ScanQuery = apacheIgnite.ScanQuery;
+
+ return {
+ listen: (server) => {
+ const io = socketio(server);
+
+ configure.socketio(io);
+
+ io.sockets.on('connection', (socket) => {
+ const user = socket.client.request.user;
+
+ socket.on('schemaImport:drivers', (cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => agent.availableDrivers())
+ .then((drivers) => cb(null, drivers))
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('schemaImport:schemas', (preset, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => {
+ const jdbcInfo = {user: preset.user, password: preset.password};
+
+ return agent.metadataSchemas(preset.jdbcDriverJar, preset.jdbcDriverClass, preset.jdbcUrl, jdbcInfo);
+ })
+ .then((schemas) => cb(null, schemas))
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('schemaImport:tables', (preset, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => {
+ const jdbcInfo = {user: preset.user, password: preset.password};
+
+ return agent.metadataTables(preset.jdbcDriverJar, preset.jdbcDriverClass, preset.jdbcUrl, jdbcInfo,
+ preset.schemas, preset.tablesOnly);
+ })
+ .then((tables) => cb(null, tables))
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('node:topology', (demo, attr, mtr, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => agent.ignite(demo).cluster(attr, mtr))
+ .then((clusters) => cb(null, clusters))
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('node:query:close', (args, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => {
+ const cache = agent.ignite(args.demo).cache(args.cacheName);
+
+ return cache.__createPromise(cache._createCommand('qrycls').addParam('qryId', args.queryId));
+ })
+ .then(() => cb())
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('node:query', (args, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => {
+ // Create sql query.
+ const qry = args.type === 'SCAN' ? new ScanQuery() : new SqlFieldsQuery(args.query);
+
+ // Set page size for query.
+ qry.setPageSize(args.pageSize);
+
+ return agent.ignite(args.demo).cache(args.cacheName).query(qry).nextPage();
+ })
+ .then((cursor) => cb(null, {
+ meta: cursor.fieldsMetadata(),
+ rows: cursor.page(),
+ queryId: cursor.queryId()
+ }))
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('node:query:fetch', (args, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => {
+ const cache = agent.ignite(args.demo).cache(args.cacheName);
+
+ const cmd = cache._createCommand('qryfetch')
+ .addParam('qryId', args.queryId)
+ .addParam('pageSize', args.pageSize);
+
+ return cache.__createPromise(cmd);
+ })
+ .then((page) => cb(null, {
+ rows: page.items,
+ last: page === null || page.last
+ }))
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('node:query:getAll', (args, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => {
+ // Create sql query.
+ const qry = args.type === 'SCAN' ? new ScanQuery() : new SqlFieldsQuery(args.query);
+
+ // Set page size for query.
+ qry.setPageSize(args.pageSize);
+
+ return agent.ignite(args.demo).cache(args.cacheName).query(qry).getAll();
+ })
+ .then((cursor) => cb(null, {
+ meta: cursor.fieldsMetadata(),
+ rows: cursor.page()
+ }))
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ socket.on('node:cache:metadata', (args, cb) => {
+ agentMgr.findAgent(user._id)
+ .then((agent) => agent.ignite(args.demo).cache(args.cacheName).metadata())
+ .then((caches) => {
+ let types = [];
+
+ const _compact = (className) => {
+ return className.replace('java.lang.', '').replace('java.util.', '').replace('java.sql.', '');
+ };
+
+ const _typeMapper = (meta, typeName) => {
+ let fields = meta.fields[typeName];
+
+ let columns = [];
+
+ for (const fieldName in fields) {
+ if (fields.hasOwnProperty(fieldName)) {
+ const fieldClass = _compact(fields[fieldName]);
+
+ columns.push({
+ type: 'field',
+ name: fieldName,
+ clazz: fieldClass,
+ system: fieldName === '_KEY' || fieldName === '_VAL',
+ cacheName: meta.cacheName,
+ typeName
+ });
+ }
+ }
+
+ const indexes = [];
+
+ for (const index of meta.indexes[typeName]) {
+ fields = [];
+
+ for (const field of index.fields) {
+ fields.push({
+ type: 'index-field',
+ name: field,
+ order: index.descendings.indexOf(field) < 0,
+ unique: index.unique,
+ cacheName: meta.cacheName,
+ typeName
+ });
+ }
+
+ if (fields.length > 0) {
+ indexes.push({
+ type: 'index',
+ name: index.name,
+ children: fields,
+ cacheName: meta.cacheName,
+ typeName
+ });
+ }
+ }
+
+ columns = _.sortBy(columns, 'name');
+
+ if (!_.isEmpty(indexes)) {
+ columns = columns.concat({
+ type: 'indexes',
+ name: 'Indexes',
+ cacheName: meta.cacheName,
+ typeName,
+ children: indexes
+ });
+ }
+
+ return {
+ type: 'type',
+ cacheName: meta.cacheName || '',
+ typeName,
+ children: columns
+ };
+ };
+
+ for (const meta of caches) {
+ const cacheTypes = meta.types.map(_typeMapper.bind(null, meta));
+
+ if (!_.isEmpty(cacheTypes))
+ types = types.concat(cacheTypes);
+ }
+
+ return cb(null, types);
+ })
+ .catch((errMsg) => cb(errMsg));
+ });
+
+ const count = agentMgr.addAgentListener(user._id, socket);
+
+ socket.emit('agent:count', {count});
+ });
+
+ io.sockets.on('disconnect', (socket) =>
+ agentMgr.removeAgentListener(socket.client.request.user._id, socket)
+ );
+ }
+ };
+};
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/mail.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/mail.js b/modules/control-center-web/src/main/js/serve/mail.js
index 8ab3e7e..36b4fa7 100644
--- a/modules/control-center-web/src/main/js/serve/mail.js
+++ b/modules/control-center-web/src/main/js/serve/mail.js
@@ -28,11 +28,12 @@ module.exports.factory = function(nodemailer, settings) {
return {
/**
* Send mail to user.
+ *
* @param {Account} user
* @param {String} subject
* @param {String} html
* @param {String} sendErr
- *
+ * @throws {Error}
* @return {Promise}
*/
send: (user, subject, html, sendErr) => {
@@ -45,7 +46,7 @@ module.exports.factory = function(nodemailer, settings) {
};
if (transporter.service === '' || transporter.auth.user === '' || transporter.auth.pass === '')
- return Promise.reject('Failed to send email. SMTP server is not configured . Please ask webmaster to setup SMTP server!');
+ throw new Error('Failed to send email. SMTP server is not configured. Please ask webmaster to setup SMTP server!');
const mailer = nodemailer.createTransport(transporter);
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/routes/agent.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/routes/agent.js b/modules/control-center-web/src/main/js/serve/routes/agent.js
index 7bb05e7..4e123bf 100644
--- a/modules/control-center-web/src/main/js/serve/routes/agent.js
+++ b/modules/control-center-web/src/main/js/serve/routes/agent.js
@@ -21,7 +21,7 @@
module.exports = {
implements: 'agent-routes',
- inject: ['require(lodash)', 'require(express)', 'require(apache-ignite)', 'require(fs)', 'require(jszip)', 'settings', 'agent']
+ inject: ['require(lodash)', 'require(express)', 'require(fs)', 'require(jszip)', 'require(apache-ignite)', 'settings', 'agent']
};
/**
@@ -34,302 +34,47 @@ module.exports = {
* @param {AgentManager} agentMgr
* @returns {Promise}
*/
-module.exports.factory = function(_, express, apacheIgnite, fs, JSZip, settings, agentMgr) {
+module.exports.factory = function(_, express, fs, JSZip, apacheIgnite, settings, agentMgr) {
return new Promise((resolveFactory) => {
const router = new express.Router();
- const SqlFieldsQuery = apacheIgnite.SqlFieldsQuery;
- const ScanQuery = apacheIgnite.ScanQuery;
-
- const _client = (userId) => {
- return new Promise((resolve, reject) => {
- const agent = agentMgr.findClient(userId);
-
- if (agent)
- return resolve(agent);
-
- reject({code: 503, message: 'Connection to Ignite Web Agent is not established'});
- });
- };
-
- const _compact = (className) => {
- return className.replace('java.lang.', '').replace('java.util.', '').replace('java.sql.', '');
- };
-
- const _handleException = (res) => {
- return (error) => {
- if (_.isObject(error))
- return res.status(error.code).send(error.message);
-
- return res.status(500).send(error);
- };
- };
-
/* Get grid topology. */
router.get('/download/zip', (req, res) => {
- const agentFld = settings.agent.file;
- const agentZip = agentFld + '.zip';
- const agentPathZip = 'public/agent/' + agentFld + '.zip';
-
- fs.stat(agentPathZip, (err, stats) => {
- if (err)
- return res.download(agentPathZip, agentZip);
-
- // Read a zip file.
- fs.readFile(agentPathZip, (errFs, data) => {
- if (errFs)
- return res.download(agentPathZip, agentZip);
-
- const zip = new JSZip(data);
-
- const prop = [];
-
- const host = req.hostname.match(/:/g) ? req.hostname.slice(0, req.hostname.indexOf(':')) : req.hostname;
-
- prop.push('token=' + req.user.token);
- prop.push('server-uri=wss://' + host + ':' + settings.agent.port);
- prop.push('#Uncomment following options if needed:');
- prop.push('#node-uri=http://localhost:8080');
- prop.push('#driver-folder=./jdbc-drivers');
- prop.push('');
- prop.push('#Note: Do not change this auto generated line');
- prop.push('rel-date=' + stats.birthtime.getTime());
-
- zip.file(agentFld + '/default.properties', prop.join('\n'));
-
- const buffer = zip.generate({type: 'nodebuffer', platform: 'UNIX'});
-
- // Set the archive name.
- res.attachment(agentZip);
-
- res.send(buffer);
- });
- });
- });
-
- /* Get grid topology. */
- router.post('/topology', (req, res) => {
- _client(req.currentUserId())
- .then((client) => client.ignite(req.body.demo).cluster(req.body.attr, req.body.mtr))
- .then((clusters) => res.json(clusters))
- .catch(_handleException(res));
- });
-
- /* Execute query. */
- router.post('/query', (req, res) => {
- _client(req.currentUserId())
- .then((client) => {
- // Create sql query.
- const qry = new SqlFieldsQuery(req.body.query);
-
- // Set page size for query.
- qry.setPageSize(req.body.pageSize);
-
- return client.ignite(req.body.demo).cache(req.body.cacheName).query(qry).nextPage();
- })
- .then((cursor) => res.json({
- meta: cursor.fieldsMetadata(),
- rows: cursor.page(),
- queryId: cursor.queryId()
- }))
- .catch(_handleException(res));
- });
-
- /* Execute query getAll. */
- router.post('/query/getAll', (req, res) => {
- _client(req.currentUserId())
- .then((client) => {
- // Create sql query.
- const qry = req.body.query ? new SqlFieldsQuery(req.body.query) : new ScanQuery();
-
- // Set page size for query.
- qry.setPageSize(1024);
-
- // Get query cursor.
- const cursor = client.ignite(req.body.demo).cache(req.body.cacheName).query(qry);
+ const latest = agentMgr.supportedAgents.latest;
- return cursor.getAll()
- .then((rows) => res.json({meta: cursor.fieldsMetadata(), rows}));
- })
- .catch(_handleException(res));
- });
-
- /* Execute query. */
- router.post('/scan', (req, res) => {
- _client(req.currentUserId())
- .then((client) => {
- // Create sql query.
- const qry = new ScanQuery();
-
- // Set page size for query.
- qry.setPageSize(req.body.pageSize);
-
- // Get query cursor.
- return client.ignite(req.body.demo).cache(req.body.cacheName).query(qry).nextPage();
- })
- .then((cursor) => res.json({
- meta: cursor.fieldsMetadata(),
- rows: cursor.page(),
- queryId: cursor.queryId()
- }))
- .catch(_handleException(res));
- });
-
- /* Get next query page. */
- router.post('/query/fetch', (req, res) => {
- _client(req.currentUserId())
- .then((client) => {
- const cache = client.ignite(req.body.demo).cache(req.body.cacheName);
-
- const cmd = cache._createCommand('qryfetch')
- .addParam('qryId', req.body.queryId)
- .addParam('pageSize', req.body.pageSize);
-
- return cache.__createPromise(cmd);
- })
- .then((page) => res.json({rows: page.items, last: page === null || page.last}))
- .catch(_handleException(res));
- });
-
- /* Close query cursor by id. */
- router.post('/query/close', (req, res) => {
- _client(req.currentUserId())
- .then((client) => {
- const cache = client.ignite(req.body.demo).cache(req.body.cacheName);
-
- return cache.__createPromise(cache._createCommand('qrycls').addParam('qryId', req.body.queryId));
- })
- .then(() => res.sendStatus(200))
- .catch(_handleException(res));
- });
-
- /* Get metadata for cache. */
- router.post('/cache/metadata', (req, res) => {
- _client(req.currentUserId())
- .then((client) => client.ignite(req.body.demo).cache(req.body.cacheName).metadata())
- .then((caches) => {
- let types = [];
-
- const _typeMapper = (meta, typeName) => {
- let fields = meta.fields[typeName];
-
- let columns = [];
-
- for (const fieldName in fields) {
- if (fields.hasOwnProperty(fieldName)) {
- const fieldClass = _compact(fields[fieldName]);
+ if (_.isEmpty(latest))
+ return res.status(500).send('Missing agent zip on server. Please ask webmaster to upload agent zip!');
- columns.push({
- type: 'field',
- name: fieldName,
- clazz: fieldClass,
- system: fieldName === '_KEY' || fieldName === '_VAL',
- cacheName: meta.cacheName,
- typeName
- });
- }
- }
+ const agentFld = latest.fileName.substr(0, latest.fileName.length - 4);
+ const agentZip = latest.fileName;
+ const agentPathZip = latest.filePath;
- const indexes = [];
-
- for (const index of meta.indexes[typeName]) {
- fields = [];
-
- for (const field of index.fields) {
- fields.push({
- type: 'index-field',
- name: field,
- order: index.descendings.indexOf(field) < 0,
- unique: index.unique,
- cacheName: meta.cacheName,
- typeName
- });
- }
-
- if (fields.length > 0) {
- indexes.push({
- type: 'index',
- name: index.name,
- children: fields,
- cacheName: meta.cacheName,
- typeName
- });
- }
- }
-
- columns = _.sortBy(columns, 'name');
-
- if (!_.isEmpty(indexes)) {
- columns = columns.concat({
- type: 'indexes',
- name: 'Indexes',
- cacheName: meta.cacheName,
- typeName,
- children: indexes
- });
- }
-
- return {
- type: 'type',
- cacheName: meta.cacheName || '',
- typeName,
- children: columns
- };
- };
-
- for (const meta of caches) {
- const cacheTypes = meta.types.map(_typeMapper.bind(null, meta));
-
- if (!_.isEmpty(cacheTypes))
- types = types.concat(cacheTypes);
- }
+ // Read a zip file.
+ fs.readFile(agentPathZip, (errFs, data) => {
+ if (errFs)
+ return res.download(agentPathZip, agentZip);
- res.json(types);
- })
- .catch(_handleException(res));
- });
+ const zip = new JSZip(data);
- /* Ping client. */
- router.post('/ping', (req, res) => {
- _client(req.currentUserId())
- .then(() => res.sendStatus(200))
- .catch(_handleException(res));
- });
+ const prop = [];
- /* Get JDBC drivers list. */
- router.post('/drivers', (req, res) => {
- _client(req.currentUserId())
- .then((client) => client.availableDrivers())
- .then((arr) => res.json(arr))
- .catch(_handleException(res));
- });
+ const host = req.hostname.match(/:/g) ? req.hostname.slice(0, req.hostname.indexOf(':')) : req.hostname;
- /** Get database schemas. */
- router.post('/schemas', (req, res) => {
- _client(req.currentUserId())
- .then((client) => {
- const args = req.body;
+ prop.push('token=' + req.user.token);
+ prop.push('server-uri=' + (settings.agent.SSLOptions ? 'https' : 'http') + '://' + host + ':' + settings.agent.port);
+ prop.push('#Uncomment following options if needed:');
+ prop.push('#node-uri=http://localhost:8080');
+ prop.push('#driver-folder=./jdbc-drivers');
- args.jdbcInfo = {user: args.user, password: args.password};
+ zip.file(agentFld + '/default.properties', prop.join('\n'));
- return client.metadataSchemas(args.jdbcDriverJar, args.jdbcDriverClass, args.jdbcUrl, args.jdbcInfo);
- })
- .then((arr) => res.json(arr))
- .catch(_handleException(res));
- });
-
- /** Get database tables. */
- router.post('/tables', (req, res) => {
- _client(req.currentUserId())
- .then((client) => {
- const args = req.body;
+ const buffer = zip.generate({type: 'nodebuffer', platform: 'UNIX'});
- args.jdbcInfo = {user: args.user, password: args.password};
+ // Set the archive name.
+ res.attachment(agentZip);
- return client.metadataTables(args.jdbcDriverJar, args.jdbcDriverClass, args.jdbcUrl, args.jdbcInfo, args.schemas, args.tablesOnly);
- })
- .then((arr) => res.json(arr))
- .catch(_handleException(res));
+ res.send(buffer);
+ });
});
resolveFactory(router);
http://git-wip-us.apache.org/repos/asf/ignite/blob/706317f3/modules/control-center-web/src/main/js/serve/routes/profile.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/serve/routes/profile.js b/modules/control-center-web/src/main/js/serve/routes/profile.js
index da6b599..9d24239 100644
--- a/modules/control-center-web/src/main/js/serve/routes/profile.js
+++ b/modules/control-center-web/src/main/js/serve/routes/profile.js
@@ -21,10 +21,18 @@
module.exports = {
implements: 'profile-routes',
- inject: ['require(lodash)', 'require(express)', 'mongo']
+ inject: ['require(lodash)', 'require(express)', 'mongo', 'agent']
};
-module.exports.factory = function(_, express, mongo) {
+/**
+ *
+ * @param _
+ * @param express
+ * @param mongo
+ * @param {AgentManager} agent
+ * @returns {Promise}
+ */
+module.exports.factory = function(_, express, mongo, agent) {
return new Promise((resolveFactory) => {
const router = new express.Router();
@@ -71,6 +79,9 @@ module.exports.factory = function(_, express, mongo) {
});
})
.then((user) => {
+ if (!params.token || user.token !== params.token)
+ agent.close(user._id);
+
for (const param in params) {
if (params.hasOwnProperty(param))
user[param] = params[param];