Repository: ambari Updated Branches: refs/heads/trunk 34741fe38 -> 1fd8eb665
AMBARI-7721. UI: REST API Changes in Storm. (Buzhor Denys via onechiporenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1fd8eb66 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1fd8eb66 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1fd8eb66 Branch: refs/heads/trunk Commit: 1fd8eb6658d22012535060cc42fbcf879795b854 Parents: 34741fe Author: Oleg Nechiporenko <onechipore...@apache.org> Authored: Fri Oct 10 14:01:33 2014 +0300 Committer: Oleg Nechiporenko <onechipore...@apache.org> Committed: Fri Oct 10 14:01:33 2014 +0300 ---------------------------------------------------------------------- .../app/controllers/global/update_controller.js | 2 +- .../app/mappers/service_metrics_mapper.js | 32 ++++-- ambari-web/app/models/service/storm.js | 2 +- ambari-web/app/utils/date.js | 2 +- ambari-web/app/utils/helper.js | 14 +++ .../app/views/main/service/services/storm.js | 5 +- .../global/update_controller_test.js | 44 +++++++- ambari-web/test/mappers/service_mapper_test.js | 108 +++++++++++++++++++ ambari-web/test/utils/helper_test.js | 106 ++++++++++++++++++ 9 files changed, 297 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/app/controllers/global/update_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/update_controller.js b/ambari-web/app/controllers/global/update_controller.js index 35b9e13..8fb056e 100644 --- a/ambari-web/app/controllers/global/update_controller.js +++ b/ambari-web/app/controllers/global/update_controller.js @@ -410,7 +410,7 @@ App.UpdateController = Em.Controller.extend({ "ServiceComponentInfo/GrayListedNodes," + "ServiceComponentInfo/BlackListedNodes," + "ServiceComponentInfo/jobtracker/*,", - 'STORM': "metrics/api/cluster/summary," + 'STORM': /^2.1/.test(App.get('currentStackVersionNumber')) ? 'metrics/api/cluster/summary' : 'metrics/api/v1/cluster/summary,metrics/api/v1/topology/summary' }; var services = App.cache['services']; services.forEach(function (service) { http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/app/mappers/service_metrics_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/service_metrics_mapper.js b/ambari-web/app/mappers/service_metrics_mapper.js index 1ee93bc..1172381 100644 --- a/ambari-web/app/mappers/service_metrics_mapper.js +++ b/ambari-web/app/mappers/service_metrics_mapper.js @@ -18,6 +18,7 @@ var App = require('app'); var misc = require('utils/misc'); var stringUtils = require('utils/string_utils'); +var dateUtils = require('utils/date'); var previousResponse = []; App.serviceMetricsMapper = App.QuickDataMapper.create({ @@ -136,13 +137,13 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({ region_servers_total: 'region_servers_total' }, stormConfig: { - total_tasks: 'restApiComponent.metrics.api.cluster.summary.["tasks.total"]', - total_slots: 'restApiComponent.metrics.api.cluster.summary.["slots.total"]', - free_slots: 'restApiComponent.metrics.api.cluster.summary.["slots.free"]', - used_slots: 'restApiComponent.metrics.api.cluster.summary.["tasks.total"]', - topologies: 'restApiComponent.metrics.api.cluster.summary.topologies', - total_executors: 'restApiComponent.metrics.api.cluster.summary.["executors.total"]', - nimbus_uptime: 'restApiComponent.metrics.api.cluster.summary.["nimbus.uptime"]', + total_tasks: 'restApiComponent.tasksTotal', + total_slots: 'restApiComponent.slotsTotal', + free_slots: 'restApiComponent.slotsFree', + used_slots: 'restApiComponent.slotsUsed', + topologies: 'restApiComponent.topologies', + total_executors: 'restApiComponent.executorsTotal', + nimbus_uptime: 'restApiComponent.nimbusUptime', super_visors_started: 'super_visors_started', super_visors_installed: 'super_visors_installed', super_visors_total: 'super_visors_total' @@ -649,9 +650,22 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({ stormMapper: function(item) { var finalConfig = jQuery.extend({}, this.config); var stormConfig = this.stormConfig; + var metricsInfoComponent = /^2.1/.test(App.get('currentStackVersionNumber')) ? 'STORM_REST_API' : 'STORM_UI_SERVER'; + var metricsPath = { + STORM_REST_API: 'metrics.api.cluster.summary', + STORM_UI_SERVER: 'metrics.api.v1.cluster.summary' + }[metricsInfoComponent]; + item.components.forEach(function(component) { - if (component.ServiceComponentInfo && component.ServiceComponentInfo.component_name == "STORM_REST_API") { - item.restApiComponent = component; + if (component.ServiceComponentInfo && component.ServiceComponentInfo.component_name == metricsInfoComponent) { + if (Em.get(component, metricsPath)) { + item.restApiComponent = App.keysDottedToCamelCase(Em.get(component, metricsPath)); + if (metricsInfoComponent == 'STORM_UI_SERVER') { + item.restApiComponent.topologies = Em.get(component, 'metrics.api.v1.topology.summary.length'); + } else { + item.restApiComponent.nimbusUptime = dateUtils.timingFormat(item.restApiComponent.nimbusUptime * 1000); + } + } finalConfig = jQuery.extend({}, finalConfig, stormConfig); } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/app/models/service/storm.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/service/storm.js b/ambari-web/app/models/service/storm.js index f061d31..e4ede81 100644 --- a/ambari-web/app/models/service/storm.js +++ b/ambari-web/app/models/service/storm.js @@ -28,7 +28,7 @@ App.StormService = App.Service.extend({ freeSlots: DS.attr('number'), totalExecutors: DS.attr('number'), topologies: DS.attr('number'), - nimbusUptime: DS.attr('number') + nimbusUptime: DS.attr('string') }); App.StormService.FIXTURES = []; http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/app/utils/date.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/date.js b/ambari-web/app/utils/date.js index 671ec02..73555b4 100644 --- a/ambari-web/app/utils/date.js +++ b/ambari-web/app/utils/date.js @@ -156,7 +156,7 @@ module.exports = { * 3500000 secs = 58.33 mins * * @param {number} time - * @param {bool} zeroValid for the case to show 0 when time is 0, not null + * @param {bool} [zeroValid] for the case to show 0 when time is 0, not null * @return {string|null} formatted date * @method timingFormat */ http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/app/utils/helper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/helper.js b/ambari-web/app/utils/helper.js index b5ce069..90d67eb 100644 --- a/ambari-web/app/utils/helper.js +++ b/ambari-web/app/utils/helper.js @@ -302,6 +302,20 @@ App.keysUnderscoreToCamelCase = function(object) { } return tmp; }; + +/** + * Convert dotted keys to camelcase + * + * @param {Object} object + * @return {Object} + **/ +App.keysDottedToCamelCase = function(object) { + var tmp = {}; + for (var key in object) { + tmp[key.split('.').reduce(function(p, c) { return p + c.capitalize()})] = object[key]; + } + return tmp; +}; /** * Returns object with defined keys only. * http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/app/views/main/service/services/storm.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/service/services/storm.js b/ambari-web/app/views/main/service/services/storm.js index 3546cd0..34242aa 100644 --- a/ambari-web/app/views/main/service/services/storm.js +++ b/ambari-web/app/views/main/service/services/storm.js @@ -44,9 +44,6 @@ App.MainDashboardServiceStormView = App.MainDashboardServiceView.extend({ }.property('service.superVisorsTotal'), nimbusUptimeFormatted: function() { - if (this.get('service.nimbusUptime') > 0) { - return date.timingFormat(this.get('service.nimbusUptime')*1000); - } - return Em.I18n.t('services.service.summary.notRunning'); + return this.get('service.nimbusUptime') || Em.I18n.t('services.service.summary.notRunning'); }.property('service.nimbusUptime') }); http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/test/controllers/global/update_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/update_controller_test.js b/ambari-web/test/controllers/global/update_controller_test.js index a880b1b..df4420e 100644 --- a/ambari-web/test/controllers/global/update_controller_test.js +++ b/ambari-web/test/controllers/global/update_controller_test.js @@ -200,15 +200,55 @@ describe('App.UpdateController', function () { } } ], - result: ["metrics/api/cluster/summary,"] + result: ["metrics/api/v1/cluster/summary," + + "metrics/api/v1/topology/summary"] } ]; + var testCasesByStackVersion = [ + { + title: 'STORM service stack 2.1', + services: [ + { + ServiceInfo: { + service_name: 'STORM' + } + } + ], + stackVersionNumber: '2.1', + result: ["metrics/api/cluster/summary"] + }, + { + title: 'STORM service stack 2.2', + services: [ + { + ServiceInfo: { + service_name: 'STORM' + } + } + ], + stackVersionNumber: '2.2', + result: ["metrics/api/v1/cluster/summary,metrics/api/v1/topology/summary"] + } + ]; testCases.forEach(function(test){ it(test.title, function () { App.cache['services'] = test.services; expect(controller.getConditionalFields()).to.eql(test.result); }); }); + + testCasesByStackVersion.forEach(function(test) { + it(test.title, function() { + App.cache['services'] = test.services; + sinon.stub(App, 'get', function(key) { + if (key == 'currentStackVersionNumber') { + return test.stackVersionNumber; + } + }); + expect(controller.getConditionalFields()).to.eql(test.result); + App.get.restore(); + }); + }); }); -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/test/mappers/service_mapper_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mappers/service_mapper_test.js b/ambari-web/test/mappers/service_mapper_test.js index e291ae7..1ab4cf9 100644 --- a/ambari-web/test/mappers/service_mapper_test.js +++ b/ambari-web/test/mappers/service_mapper_test.js @@ -85,4 +85,112 @@ describe('App.serviceMetricsMapper', function () { }); }); + describe('#stormMapper', function() { + var tests = [ + { + stackVersionNumber: '2.2', + message: 'Storm mapper, stack version 2.2', + expectedValues: { + total_executors: 28, + nimbus_uptime: "15m 1s", + free_slots: 0, + used_slots: 2, + total_slots: 2, + total_tasks: 28, + topologies: 1 + }, + components: [ + { + "ServiceComponentInfo" : { + "component_name" : "STORM_UI_SERVER", + "service_name" : "STORM" + }, + "metrics" : { + "api" : { + "v1": { + "cluster": { + "summary": { + "executorsTotal": 28.0, + "nimbusUptime": "15m 1s", + "slotsFree": 0.0, + "slotsTotal": 2.0, + "slotsUsed": 2.0, + "supervisors": 1.0, + "tasksTotal": 28.0 + } + }, + "topology": { + "summary": [ + { + "executorsTotal": 21.0, + "uptime": "5m 59s", + "schedulerInfo": null, + "name": "WordCountida8c06640_date2901141", + "workersTotal": 2.0, + "status": "ACTIVE", + "owner": "", + "tasksTotal": 21.0, + "id": "WordCountida8c06640_date2901141-2-1412195707" + } + ] + } + } + } + } + } + ] + }, + { + stackVersionNumber: '2.1', + message: 'Storm mapper, stack version 2.1', + expectedValues: { + total_executors: 2, + nimbus_uptime: "3.96 hours", + free_slots: 2, + used_slots: 0, + total_slots: 2, + total_tasks: 21, + topologies: 0 + }, + components: [ + { + "ServiceComponentInfo" : { + "component_name" : "STORM_REST_API", + "service_name" : "STORM" + }, + "metrics" : { + "api" : { + "cluster" : { + "summary" : { + "executors.total" : 2.0, + "nimbus.uptime" : 14250.0, + "slots.free" : 2.0, + "slots.total" : 2.0, + "slots.used" : 0.0, + "supervisors" : 1.0, + "tasks.total" : 21.0, + "topologies" : 0.0 + } + } + } + } + } + ] + } + ]; + + tests.forEach(function(test) { + it(test.message, function() { + sinon.stub(App, 'get', function(key) { + if (key == 'currentStackVersionNumber') { + return test.stackVersionNumber; + } + }); + var result = App.serviceMetricsMapper.stormMapper(test); + expect(result).to.include(test.expectedValues); + App.get.restore(); + }); + }); + + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/1fd8eb66/ambari-web/test/utils/helper_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/utils/helper_test.js b/ambari-web/test/utils/helper_test.js index f75c1e4..9274ae0 100644 --- a/ambari-web/test/utils/helper_test.js +++ b/ambari-web/test/utils/helper_test.js @@ -318,7 +318,113 @@ describe('utils/helper', function() { expect(App.permit(obj, test.keys)).to.deep.eql(test.e); }); }); + }); + describe('#App.keysUnderscoreToCamelCase()', function() { + var tests = [ + { + object: { + 'key_upper': '2' + }, + expected: { + keyUpper: '2' + }, + m: 'One level object, key should be camelCased' + }, + { + object: { + 'key_upper': '2', + 'key': '1' + }, + expected: { + keyUpper: '2', + key: '1' + }, + m: 'One level object, one key should be camelCased.' + }, + { + object: { + 'key_upper': '2', + 'key': '1' + }, + expected: { + keyUpper: '2', + key: '1' + }, + m: 'One level object, one key should be camelCased.' + }, + { + object: { + 'key_upper': '2', + 'key_upone_uptwo_upthree': '4', + 'key': '1' + }, + expected: { + keyUpper: '2', + keyUponeUptwoUpthree: '4', + key: '1' + }, + m: 'One level object, two keys should be camelCased, few dots notation.' + } + ]; + tests.forEach(function(test) { + it(test.m, function() { + expect(App.keysUnderscoreToCamelCase(test.object)).to.deep.equal(test.expected); + }); + }); + }); + describe('#App.keysDottedToCamelCase()', function() { + var tests = [ + { + object: { + 'key.upper': '2' + }, + expected: { + keyUpper: '2' + }, + m: 'One level object, key should be camelCased' + }, + { + object: { + 'key.upper': '2', + 'key': '1' + }, + expected: { + keyUpper: '2', + key: '1' + }, + m: 'One level object, one key should be camelCased.' + }, + { + object: { + 'key.upper': '2', + 'key': '1' + }, + expected: { + keyUpper: '2', + key: '1' + }, + m: 'One level object, one key should be camelCased.' + }, + { + object: { + 'key.upper': '2', + 'key.upone.uptwo.upthree': '4', + 'key': '1' + }, + expected: { + keyUpper: '2', + keyUponeUptwoUpthree: '4', + key: '1' + }, + m: 'One level object, two keys should be camelCased, few dots notation.' + } + ]; + tests.forEach(function(test) { + it(test.m, function() { + expect(App.keysDottedToCamelCase(test.object)).to.deep.equal(test.expected); + }); + }); }); });