Repository: ambari Updated Branches: refs/heads/trunk f543cc6c0 -> beccf117a
AMBARI-8399. Alerts UI: Alerts Instances keep storing in DS.Store even after user navigate away (onechiporenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/beccf117 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/beccf117 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/beccf117 Branch: refs/heads/trunk Commit: beccf117a3e002afe39c7f75abdc553b55486d1c Parents: f543cc6 Author: Oleg Nechiporenko <onechipore...@apache.org> Authored: Thu Nov 20 19:46:33 2014 +0200 Committer: Oleg Nechiporenko <onechipore...@apache.org> Committed: Thu Nov 20 19:46:33 2014 +0200 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 1 + .../main/alerts/alert_instances_controller.js | 109 ++++++++++---- .../app/mappers/alert_instances_mapper.js | 24 +++ .../alerts/alert_instances_controller_test.js | 4 +- .../test/mappers/alert_instances_mapper_test.js | 145 +++++++++++++++++++ 5 files changed, 252 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/beccf117/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 8fb8688..c831716 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -110,6 +110,7 @@ var files = ['test/init_model_test', 'test/login_test', 'test/router_test', 'test/mappers/alert_groups_mapper_test', + 'test/mappers/alert_instances_mapper_test', 'test/mappers/alert_definitions_mapper_test', 'test/mappers/alert_definition_summary_mapper_test', 'test/mappers/server_data_mapper_test', http://git-wip-us.apache.org/repos/asf/ambari/blob/beccf117/ambari-web/app/controllers/main/alerts/alert_instances_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/alerts/alert_instances_controller.js b/ambari-web/app/controllers/main/alerts/alert_instances_controller.js index 02a0577..93d2994 100644 --- a/ambari-web/app/controllers/main/alerts/alert_instances_controller.js +++ b/ambari-web/app/controllers/main/alerts/alert_instances_controller.js @@ -19,60 +19,86 @@ var App = require('app'); App.MainAlertInstancesController = Em.Controller.extend({ + name: 'mainAlertInstancesController', + + /** + * Are alertInstances loaded + * @type {boolean} + */ isLoaded: false, + /** * Causes automatic updates of content if set to true + * @type {boolean} */ isUpdating: false, + + /** + * Times for alert instances updater + * Used in <code>scheduleUpdate</code> + * @type {number|null} + */ updateTimer: null, - updateInterval: App.alertInstancesUpdateInterval, + /** - * "HOST" or "ALERT_DEFINITION" + * @type {string|null} sourceName - hostName or alertDefinitionId */ - sourceType: null, sourceName: null, + /** + * @type {string|null} sourceType - 'HOST'|'ALERT_DEFINITION' + */ + sourceType: null, + + /** + * Load alert instances from server (all, for selected host, for selected alert definition) + * @returns {$.ajax} + * @method fetchAlertInstances + */ fetchAlertInstances: function () { - switch (this.get('sourceType')) { + var sourceType = this.get('sourceType'), + sourceName = this.get('sourceName'), + ajaxData = { + sender: this, + success: 'getAlertInstancesSuccessCallback', + error: 'getAlertInstancesErrorCallback' + }; + + switch (sourceType) { case 'HOST': - App.ajax.send({ + $.extend(ajaxData, { name: 'alerts.instances.by_host', - sender: this, data: { - clusterName: App.router.get('clusterName'), - hostName: this.get('sourceName') - }, - success: 'getAlertInstancesSuccessCallback', - error: 'getAlertInstancesErrorCallback' + hostName: sourceName + } }); break; + case 'ALERT_DEFINITION': - App.ajax.send({ + $.extend(ajaxData, { name: 'alerts.instances.by_definition', - sender: this, data: { - clusterName: App.router.get('clusterName'), - definitionId: this.get('sourceName') - }, - success: 'getAlertInstancesSuccessCallback', - error: 'getAlertInstancesErrorCallback' + definitionId: sourceName + } }); break; + default: - App.ajax.send({ - name: 'alerts.instances', - sender: this, - data: { - clusterName: App.router.get('clusterName') - }, - success: 'getAlertInstancesSuccessCallback', - error: 'getAlertInstancesErrorCallback' + $.extend(ajaxData, { + name: 'alerts.instances' }); break; } + + return App.ajax.send(ajaxData); }, + /** + * Pseudo for <code>fetchAlertInstances</code> + * Used to get all alert instances + * @method loadAlertInstances + */ loadAlertInstances: function () { this.set('isLoaded', false); this.set('sourceType', null); @@ -80,6 +106,12 @@ App.MainAlertInstancesController = Em.Controller.extend({ this.fetchAlertInstances(); }, + /** + * Pseudo for <code>fetchAlertInstances</code> + * Used to get alert instances for some host + * @param {string} hostName + * @method loadAlertInstancesByHost + */ loadAlertInstancesByHost: function (hostName) { this.set('isLoaded', false); this.set('sourceType', 'HOST'); @@ -87,10 +119,16 @@ App.MainAlertInstancesController = Em.Controller.extend({ this.fetchAlertInstances(); }, - loadAlertInstancesByAlertDefinition: function (definitionName) { + /** + * Pseudo for <code>fetchAlertInstances</code> + * Used to get alert instances for some alert definition + * @param {string} definitionId + * @method loadAlertInstancesByAlertDefinition + */ + loadAlertInstancesByAlertDefinition: function (definitionId) { this.set('isLoaded', false); this.set('sourceType', 'ALERT_DEFINITION'); - this.set('sourceName', definitionName); + this.set('sourceName', definitionId); this.fetchAlertInstances(); }, @@ -100,18 +138,29 @@ App.MainAlertInstancesController = Em.Controller.extend({ this.set('updateTimer', setTimeout(function () { self.fetchAlertInstances(); self.scheduleUpdate(); - }, this.get('updateInterval'))); - } else { + }, App.get('alertInstancesUpdateInterval'))); + } + else { clearTimeout(this.get('updateTimer')); } }.observes('isUpdating'), + /** + * Success-callback for alert instances request + * @param {object} json + * @method getAlertInstancesSuccessCallback + */ getAlertInstancesSuccessCallback: function (json) { App.alertInstanceMapper.map(json); this.set('isLoaded', true); }, + /** + * Error-callback for alert instances request + * @method getAlertInstancesErrorCallback + */ getAlertInstancesErrorCallback: function () { this.set('isLoaded', true); } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/beccf117/ambari-web/app/mappers/alert_instances_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/alert_instances_mapper.js b/ambari-web/app/mappers/alert_instances_mapper.js index 9544882..468d66c 100644 --- a/ambari-web/app/mappers/alert_instances_mapper.js +++ b/ambari-web/app/mappers/alert_instances_mapper.js @@ -18,7 +18,9 @@ var App = require('app'); App.alertInstanceMapper = App.QuickDataMapper.create({ + model : App.AlertInstance, + config : { id: 'Alert.id', label: 'Alert.label', @@ -34,5 +36,27 @@ App.alertInstanceMapper = App.QuickDataMapper.create({ instance: 'Alert.instance', state: 'Alert.state', text: 'Alert.text' + }, + + map: function(json) { + if (json.items) { + var self = this, + alertInstances = [], + model = this.get('model'), + alertsToDelete = model.find().mapProperty('id'); + + json.items.forEach(function (item) { + var alert = this.parseIt(item, this.get('config')); + alertInstances.push(alert); + alertsToDelete = alertsToDelete.without(alert.id); + }, this); + + alertsToDelete.forEach(function(alertId) { + self.deleteRecord(model.find(alertId)); + }); + + App.store.loadMany(model, alertInstances); + } } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/beccf117/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js b/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js index 9c49c90..8f24e5a 100644 --- a/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js +++ b/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js @@ -20,7 +20,7 @@ var App = require('app'); var controller; -describe('App.MainAlertDefinitionActionsController', function () { +describe('App.MainAlertInstancesController', function () { beforeEach(function () { controller = App.MainAlertInstancesController.create({}); @@ -43,6 +43,7 @@ describe('App.MainAlertDefinitionActionsController', function () { controller.loadAlertInstancesByHost('host'); console.log(App.ajax.send.args[0]); expect(App.ajax.send.args[0][0].name).to.equal('alerts.instances.by_host'); + expect(App.ajax.send.args[0][0].data.hostName).to.equal('host'); }); @@ -51,6 +52,7 @@ describe('App.MainAlertDefinitionActionsController', function () { controller.loadAlertInstancesByAlertDefinition('1'); console.log(App.ajax.send.args[0]); expect(App.ajax.send.args[0][0].name).to.equal('alerts.instances.by_definition'); + expect(App.ajax.send.args[0][0].data.definitionId).to.equal('1'); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/beccf117/ambari-web/test/mappers/alert_instances_mapper_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mappers/alert_instances_mapper_test.js b/ambari-web/test/mappers/alert_instances_mapper_test.js new file mode 100644 index 0000000..9096d3e --- /dev/null +++ b/ambari-web/test/mappers/alert_instances_mapper_test.js @@ -0,0 +1,145 @@ +/** + * 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/alert_instances_mapper'); +var testHelpers = require('test/helpers'); + +describe('App.alertInstanceMapper', function () { + + var alertInstances = [ + {id: 1}, + {id: 2}, + {id: 3}, + {id: 4} + ], + json = { + "items" : [ + { + "Alert" : { + "component_name" : "AMBARI_AGENT", + "host_name" : "c6401.ambari.apache.org", + "id" : 2, + "instance" : null, + "label" : "Ambari Agent Disk Usage", + "latest_timestamp" : 1415224354954, + "maintenance_state" : "OFF", + "name" : "ambari_agent_disk_usage", + "original_timestamp" : 1414695835400, + "scope" : "HOST", + "service_name" : "AMBARI", + "state" : "OK", + "text" : "Capacity Used: [1.26%, 6.6 GB], Capacity Total: [525.3 GB]" + } + }, + { + "Alert" : { + "component_name" : null, + "host_name" : null, + "id" : 3, + "instance" : null, + "label" : "Percent DataNodes Available", + "latest_timestamp" : 1415224362617, + "maintenance_state" : "OFF", + "name" : "datanode_process_percent", + "original_timestamp" : 1414695787466, + "scope" : "SERVICE", + "service_name" : "HDFS", + "state" : "CRITICAL", + "text" : "affected: [1], total: [1]" + } + } + ] + }; + + beforeEach(function () { + + sinon.stub(App.alertInstanceMapper, 'deleteRecord', Em.K); + + sinon.stub(App.store, 'loadMany', function (type, content) { + type.content = content; + }); + + App.alertInstanceMapper.model = { + find: function () { + if (arguments.length) { + return alertInstances.findProperty('id', arguments[0]); + } + return alertInstances; + } + }; + + }); + + afterEach(function () { + + App.alertInstanceMapper.deleteRecord.restore(); + App.alertInstanceMapper.model = App.AlertInstance; + App.store.loadMany.restore(); + + }); + + it('should delete not existing models', function () { + + App.alertInstanceMapper.map(json); + + expect(App.alertInstanceMapper.deleteRecord.calledTwice).to.be.true; + expect(App.alertInstanceMapper.deleteRecord.args[0][0].id).to.equal(1); + expect(App.alertInstanceMapper.deleteRecord.args[1][0].id).to.equal(4); + + }); + + it('should map alert instances', function () { + + var expected = [ + { + "id": 2, + "label": "Ambari Agent Disk Usage", + "service_id": "AMBARI", + "component_name": "AMBARI_AGENT", + "host_id": "c6401.ambari.apache.org", + "scope": "HOST", + "original_timestamp": 1414695835400, + "latest_timestamp": 1415224354954, + "maintenance_state": "OFF", + "instance": null, + "state": "OK", + "text": "Capacity Used: [1.26%, 6.6 GB], Capacity Total: [525.3 GB]" + }, + { + "id": 3, + "label": "Percent DataNodes Available", + "service_id": "HDFS", + "component_name": null, + "host_id": null, + "scope": "SERVICE", + "original_timestamp": 1414695787466, + "latest_timestamp": 1415224362617, + "maintenance_state": "OFF", + "instance": null, + "state": "CRITICAL", + "text": "affected: [1], total: [1]" + } + ]; + + App.alertInstanceMapper.map(json); + testHelpers.nestedExpect(expected, App.alertInstanceMapper.model.content); + + }); + +}); \ No newline at end of file