Repository: ambari Updated Branches: refs/heads/branch-3.0-perf 05cd35982 -> eec5936bd
AMBARI-22441 Integrate Alert Groups on Alert page with websocket events. (atkach) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/eec5936b Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/eec5936b Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/eec5936b Branch: refs/heads/branch-3.0-perf Commit: eec5936bd4819ca83f65c2456c71f83ca59b4f2d Parents: 05cd359 Author: Andrii Tkach <atk...@apache.org> Authored: Wed Nov 15 11:32:58 2017 +0200 Committer: Andrii Tkach <atk...@apache.org> Committed: Wed Nov 15 11:32:58 2017 +0200 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 1 + .../app/controllers/global/update_controller.js | 3 +- .../alert_definitions_actions_controller.js | 7 +- .../manage_alert_notifications_controller.js | 13 ++-- ambari-web/app/mappers.js | 1 + ambari-web/app/mappers/alert_groups_mapper.js | 10 +-- .../socket/alert_groups_mapper_adapter.js | 41 ++++++++++++ .../main/alerts/definition_details_view.js | 25 +++---- .../global/update_controller_test.js | 4 +- .../socket/alert_groups_mapper_adapter_test.js | 70 ++++++++++++++++++++ .../main/alerts/definition_details_view_test.js | 48 +++++--------- 11 files changed, 156 insertions(+), 67 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/app/assets/test/tests.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js index eac9967..23b985a 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -173,6 +173,7 @@ var files = [ 'test/mappers/socket/service_state_mapper_test', 'test/mappers/socket/host_state_mapper_test', 'test/mappers/socket/alert_definitions_mapper_adapter_test', + 'test/mappers/socket/alert_groups_mapper_adapter_test', 'test/mixins/common/configs/enhanced_configs_test', 'test/mixins/common/configs/config_recommendations_test', 'test/mixins/common/configs/config_recommendation_parser_test', http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/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 63a4da4..9a5ae20 100644 --- a/ambari-web/app/controllers/global/update_controller.js +++ b/ambari-web/app/controllers/global/update_controller.js @@ -194,6 +194,7 @@ App.UpdateController = Em.Controller.extend({ App.StompClient.subscribe('/events/services', App.serviceStateMapper.map.bind(App.serviceStateMapper)); App.StompClient.subscribe('/events/hosts', App.hostStateMapper.map.bind(App.hostStateMapper)); App.StompClient.subscribe('/events/alert_definitions', App.alertDefinitionsMapperAdapter.map.bind(App.alertDefinitionsMapperAdapter)); + App.StompClient.subscribe('/events/alert_group', App.alertGroupsMapperAdapter.map.bind(App.alertGroupsMapperAdapter)); App.updater.run(this, 'updateHostsMetrics', 'isWorking', App.contentUpdateInterval, '\/main\/(hosts).*'); App.updater.run(this, 'updateServiceMetric', 'isWorking', App.componentsUpdateInterval, '\/main\/(dashboard|services).*'); @@ -201,7 +202,6 @@ App.UpdateController = Em.Controller.extend({ App.updater.run(this, 'graphsUpdate', 'isWorking'); App.updater.run(this, 'updateComponentConfig', 'isWorking'); - App.updater.run(this, 'updateAlertGroups', 'isWorking', App.alertGroupsUpdateInterval, '\/main\/alerts.*'); if (!App.get('router.mainAlertInstancesController.isUpdating')) { App.updater.run(this, 'updateUnhealthyAlertInstances', 'updateAlertInstances', App.alertInstancesUpdateInterval, '\/main\/alerts.*'); } @@ -215,6 +215,7 @@ App.UpdateController = Em.Controller.extend({ App.StompClient.unsubscribe('/events/services'); App.StompClient.unsubscribe('/events/hosts'); App.StompClient.unsubscribe('/events/alert_definitions'); + App.StompClient.unsubscribe('/events/alert_group'); } }.observes('isWorking', 'App.router.mainAlertInstancesController.isUpdating'), http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/app/controllers/main/alerts/alert_definitions_actions_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/alerts/alert_definitions_actions_controller.js b/ambari-web/app/controllers/main/alerts/alert_definitions_actions_controller.js index 71d9acf..bca0d22 100644 --- a/ambari-web/app/controllers/main/alerts/alert_definitions_actions_controller.js +++ b/ambari-web/app/controllers/main/alerts/alert_definitions_actions_controller.js @@ -165,12 +165,7 @@ App.MainAlertDefinitionActionsController = Em.ArrayController.extend({ }) }); } - App.router.get('updateController').updateAlertGroups(function () { - App.router.get('manageAlertGroupsController').toggleProperty('changeTrigger'); - App.router.get('updateController').updateAlertDefinitions(function() { - App.router.get('updateController').updateAlertNotifications(Em.K); - }); - }); + App.router.get('updateController').updateAlertNotifications(Em.K); } } else { runNextQuery(); http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js b/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js index a417a73..ddb8874 100644 --- a/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js +++ b/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js @@ -358,15 +358,12 @@ App.ManageAlertNotificationsController = Em.Controller.extend({ * @method loadAlertNotifications */ loadAlertNotifications: function () { - var self = this; this.set('isLoaded', false); - App.router.get('updateController').updateAlertGroups(function () { - App.ajax.send({ - name: 'alerts.notifications', - sender: self, - success: 'getAlertNotificationsSuccessCallback', - error: 'getAlertNotificationsErrorCallback' - }); + return App.ajax.send({ + name: 'alerts.notifications', + sender: this, + success: 'getAlertNotificationsSuccessCallback', + error: 'getAlertNotificationsErrorCallback' }); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/app/mappers.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers.js b/ambari-web/app/mappers.js index 241ba29..945b1dc 100644 --- a/ambari-web/app/mappers.js +++ b/ambari-web/app/mappers.js @@ -51,3 +51,4 @@ require('mappers/socket/host_component_status_mapper'); require('mappers/socket/alert_summary_mapper'); require('mappers/socket/host_state_mapper'); require('mappers/socket/alert_definitions_mapper_adapter'); +require('mappers/socket/alert_groups_mapper_adapter'); http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/app/mappers/alert_groups_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/alert_groups_mapper.js b/ambari-web/app/mappers/alert_groups_mapper.js index 1fd38f5..3e86a1d 100644 --- a/ambari-web/app/mappers/alert_groups_mapper.js +++ b/ambari-web/app/mappers/alert_groups_mapper.js @@ -39,7 +39,7 @@ App.alertGroupsMapper = App.QuickDataMapper.create({ } }, - map: function (json) { + map: function (json, ignoreDelete) { if(Em.isNone(App.cache['previousAlertGroupsFullMap'])) { App.cache['previousAlertGroupsFullMap'] = {}; } @@ -101,9 +101,11 @@ App.alertGroupsMapper = App.QuickDataMapper.create({ }, this); - groupsToDelete.forEach(function(groupId) { - self.deleteRecord(App.AlertGroup.find(groupId)); - }); + if (!ignoreDelete) { + groupsToDelete.forEach(function(groupId) { + self.deleteRecord(App.AlertGroup.find(groupId)); + }); + } App.cache['previousAlertGroupsMap'] = alertDefinitionsGroupsMap; App.cache['previousAlertGroupsFullMap'] = groupsMap; http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/app/mappers/socket/alert_groups_mapper_adapter.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/socket/alert_groups_mapper_adapter.js b/ambari-web/app/mappers/socket/alert_groups_mapper_adapter.js new file mode 100644 index 0000000..c325da3 --- /dev/null +++ b/ambari-web/app/mappers/socket/alert_groups_mapper_adapter.js @@ -0,0 +1,41 @@ +/** + * 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. + */ + +var App = require('app'); + +App.alertGroupsMapperAdapter = App.QuickDataMapper.create({ + + /** + * @param {object} event + */ + map: function(event) { + event.groups.forEach((alertGroup) => { + if (event.updateType === 'UPDATE' || event.updateType === 'CREATE') { + App.alertGroupsMapper.map({ + items: [ + { + AlertGroup: alertGroup + } + ] + }, true); + } else if (event.updateType === 'DELETE') { + this.deleteRecord(App.AlertGroup.find(alertGroup.id)); + } + }); + App.router.get('manageAlertGroupsController').toggleProperty('changeTrigger'); + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/app/views/main/alerts/definition_details_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/alerts/definition_details_view.js b/ambari-web/app/views/main/alerts/definition_details_view.js index bb9e738..68d7ea4 100644 --- a/ambari-web/app/views/main/alerts/definition_details_view.js +++ b/ambari-web/app/views/main/alerts/definition_details_view.js @@ -66,25 +66,18 @@ App.MainAlertDefinitionDetailsView = App.TableView.extend({ this.set('isLoaded', true); this.get('controller').loadAlertInstances(); } else { - this.loadDefinitionDetails(); + App.router.get('clusterController').addObserver('isAlertsLoaded', this, 'loadAfterModelLoaded'); } }, - loadDefinitionDetails: function() { - var self = this, - updater = App.router.get('updateController'); - - updater.updateAlertGroups(function () { - updater.updateAlertDefinitions(function () { - updater.updateAlertDefinitionSummary(function () { - self.set('isLoaded', true); - // App.AlertDefinition doesn't represents real models - // Real model (see AlertDefinition types) should be used - self.set('controller.content', App.AlertDefinition.find(parseInt(self.get('controller.content.id')))); - self.get('controller').loadAlertInstances(); - }); - }); - }); + loadAfterModelLoaded: function() { + var clusterController = App.router.get('clusterController'); + if (clusterController.get('isAlertsLoaded')) { + this.set('isLoaded', true); + this.set('controller.content', App.AlertDefinition.find(parseInt(this.get('controller.content.id')))); + this.get('controller').loadAlertInstances(); + clusterController.removeObserver('isAlertsLoaded', this, 'loadAfterModelLoaded'); + } }, nameValidation: function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/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 c42926a..f842654 100644 --- a/ambari-web/test/controllers/global/update_controller_test.js +++ b/ambari-web/test/controllers/global/update_controller_test.js @@ -75,11 +75,12 @@ describe('App.UpdateController', function () { expect(App.StompClient.unsubscribe.calledWith('/events/services')).to.be.true; expect(App.StompClient.unsubscribe.calledWith('/events/hosts')).to.be.true; expect(App.StompClient.unsubscribe.calledWith('/events/alert_definitions')).to.be.true; + expect(App.StompClient.unsubscribe.calledWith('/events/alert_group')).to.be.true; }); it('isWorking = true', function () { controller.set('isWorking', true); - expect(App.updater.run.callCount).to.equal(9); + expect(App.updater.run.callCount).to.equal(8); expect(App.StompClient.subscribe.calledWith('/events/hostcomponents')).to.be.true; expect(App.StompClient.subscribe.calledWith('/events/alerts')).to.be.true; expect(App.StompClient.subscribe.calledWith('/events/ui_topologies')).to.be.true; @@ -87,6 +88,7 @@ describe('App.UpdateController', function () { expect(App.StompClient.subscribe.calledWith('/events/services')).to.be.true; expect(App.StompClient.subscribe.calledWith('/events/hosts')).to.be.true; expect(App.StompClient.subscribe.calledWith('/events/alert_definitions')).to.be.true; + expect(App.StompClient.subscribe.calledWith('/events/alert_group')).to.be.true; }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/test/mappers/socket/alert_groups_mapper_adapter_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mappers/socket/alert_groups_mapper_adapter_test.js b/ambari-web/test/mappers/socket/alert_groups_mapper_adapter_test.js new file mode 100644 index 0000000..ab1684e --- /dev/null +++ b/ambari-web/test/mappers/socket/alert_groups_mapper_adapter_test.js @@ -0,0 +1,70 @@ +/** + * 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. + */ + +var App = require('app'); + +require('mappers/socket/alert_groups_mapper_adapter'); + +describe('App.alertGroupsMapperAdapter', function () { + + describe('#map', function() { + beforeEach(function() { + sinon.stub(App.alertGroupsMapper, 'map'); + sinon.stub(App.AlertGroup, 'find').returns({}); + sinon.stub(App.alertGroupsMapperAdapter, 'deleteRecord'); + App.set('clusterId', 1); + }); + afterEach(function() { + App.alertGroupsMapper.map.restore(); + App.AlertGroup.find.restore(); + App.alertGroupsMapperAdapter.deleteRecord.restore(); + }); + + it('should call App.alertGroupsMapper.map on UPDATE event', function() { + var event = { + updateType: 'UPDATE', + groups: [ + { + id: 1 + } + ] + }; + App.alertGroupsMapperAdapter.map(event); + expect(App.alertGroupsMapper.map.getCall(0).args[0]).to.be.eql({ + items: [{ + AlertGroup: { + id: 1 + } + }] + }); + }); + + it('should call deleteRecord on DELETE event', function() { + var event = { + updateType: 'DELETE', + groups: [ + { + id: 1 + } + ] + }; + App.alertGroupsMapperAdapter.map(event); + expect(App.alertGroupsMapperAdapter.deleteRecord.calledWith({})).to.be.true; + }); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/eec5936b/ambari-web/test/views/main/alerts/definition_details_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/alerts/definition_details_view_test.js b/ambari-web/test/views/main/alerts/definition_details_view_test.js index 7b96858..9813573 100644 --- a/ambari-web/test/views/main/alerts/definition_details_view_test.js +++ b/ambari-web/test/views/main/alerts/definition_details_view_test.js @@ -42,13 +42,15 @@ describe('App.MainAlertDefinitionDetailsView', function () { beforeEach(function() { sinon.spy(view.get('controller'), 'clearStep'); sinon.spy(view.get('controller'), 'loadAlertInstances'); - sinon.stub(view, 'loadDefinitionDetails'); + sinon.stub(App.router, 'get').returns({ + addObserver: sinon.spy() + }); }); afterEach(function() { view.get('controller').clearStep.restore(); view.get('controller').loadAlertInstances.restore(); - view.loadDefinitionDetails.restore(); + App.router.get.restore(); }); it("clearStep() should be called", function() { @@ -67,52 +69,36 @@ describe('App.MainAlertDefinitionDetailsView', function () { view.set('controller.content.isLoaded', false); view.willInsertElement(); expect(view.get('isLoaded')).to.be.false; - expect(view.loadDefinitionDetails.calledOnce).to.be.true; + expect(App.router.get('clusterController').addObserver.calledWith('isAlertsLoaded', view, 'loadAfterModelLoaded')).to.be.true; }); }); - describe("#loadDefinitionDetails()", function() { - var mock = { - updateAlertGroups: function(callback) { callback(); }, - updateAlertDefinitions: function(callback) { callback(); }, - updateAlertDefinitionSummary: function(callback) { callback(); } - }; - + describe('#loadAfterModelLoaded', function() { beforeEach(function() { - sinon.stub(App.router, 'get').returns(mock); - sinon.spy(mock, 'updateAlertGroups'); - sinon.spy(mock, 'updateAlertDefinitions'); - sinon.spy(mock, 'updateAlertDefinitionSummary'); + sinon.stub(App.router, 'get').returns(Em.Object.create({ + removeObserver: sinon.spy(), + isAlertsLoaded: true + })); sinon.stub(view.get('controller'), 'loadAlertInstances'); sinon.stub(App.AlertDefinition, 'find').returns({}); - - view.loadDefinitionDetails(); + view.set('isLoaded', false); + view.loadAfterModelLoaded(); }); - afterEach(function() { App.router.get.restore(); - mock.updateAlertGroups.restore(); - mock.updateAlertDefinitions.restore(); - mock.updateAlertDefinitionSummary.restore(); view.get('controller').loadAlertInstances.restore(); App.AlertDefinition.find.restore(); }); - it("updateAlertGroups() should be called", function() { - expect(mock.updateAlertGroups.calledOnce).to.be.true; - }); - - it("updateAlertDefinitions() should be called", function() { - expect(mock.updateAlertDefinitions.calledOnce).to.be.true; + it('isLoaded should be true', function() { + expect(view.get('isLoaded')).to.be.true; }); - it("updateAlertDefinitionSummary() should be called", function() { - expect(mock.updateAlertDefinitionSummary.calledOnce).to.be.true; + it('content should be set', function() { + expect(view.get('controller.content')).to.be.object; }); - it("loadAlertInstances() should be called", function() { - expect(view.get('isLoaded')).to.be.true; - expect(view.get('controller.content')).to.eql({}); + it('loadAlertInstances should be called', function() { expect(view.get('controller').loadAlertInstances.calledOnce).to.be.true; }); });