AMBARI-20165 Cover NameNode HA wizard with unit tests. (atkach)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b511b5b2 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b511b5b2 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b511b5b2 Branch: refs/heads/trunk Commit: b511b5b22d02b056d98aac675c9e4fa67866cfa4 Parents: 6277a64 Author: Andrii Tkach <[email protected]> Authored: Fri Feb 24 12:00:10 2017 +0200 Committer: Andrii Tkach <[email protected]> Committed: Fri Feb 24 14:56:29 2017 +0200 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 7 + .../nameNode/step2_controller.js | 5 +- .../nameNode/step3_controller.js | 24 +- .../nameNode/step4_controller.js | 6 +- .../nameNode/step5_controller.js | 30 +- .../nameNode/step6_controller.js | 34 +- .../nameNode/step9_controller.js | 76 ++-- .../nameNode/step1_controller_test.js | 132 ++++++ .../nameNode/step2_controller_test.js | 86 +++- .../nameNode/step3_controller_test.js | 209 +++++++++- .../nameNode/step4_controller_test.js | 80 +++- .../nameNode/step5_controller_test.js | 312 ++++++++++++++ .../nameNode/step6_controller_test.js | 195 +++++++++ .../nameNode/step7_controller_test.js | 122 ++++++ .../nameNode/step8_controller_test.js | 53 +++ .../nameNode/step9_controller_test.js | 342 +++++++++++++++ .../nameNode/wizard_controller_test.js | 418 +++++++++++++++++++ 17 files changed, 2027 insertions(+), 104 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/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 05c1657..308edcd 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -72,9 +72,16 @@ var files = [ 'test/controllers/main/admin/highAvailability_controller_test', 'test/controllers/main/admin/highAvailability/progress_controller_test', 'test/controllers/main/admin/highAvailability/progress_popup_controller_test', + 'test/controllers/main/admin/highAvailability/nameNode/step1_controller_test', 'test/controllers/main/admin/highAvailability/nameNode/step2_controller_test', 'test/controllers/main/admin/highAvailability/nameNode/step3_controller_test', 'test/controllers/main/admin/highAvailability/nameNode/step4_controller_test', + 'test/controllers/main/admin/highAvailability/nameNode/step5_controller_test', + 'test/controllers/main/admin/highAvailability/nameNode/step6_controller_test', + 'test/controllers/main/admin/highAvailability/nameNode/step7_controller_test', + 'test/controllers/main/admin/highAvailability/nameNode/step8_controller_test', + 'test/controllers/main/admin/highAvailability/nameNode/step9_controller_test', + 'test/controllers/main/admin/highAvailability/nameNode/wizard_controller_test', 'test/controllers/main/admin/highAvailability/resourceManager/step3_controller_test', 'test/controllers/main/admin/highAvailability/resourceManager/step4_controller_test', 'test/controllers/main/admin/highAvailability/resourceManager/wizard_controller_test', http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step2_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step2_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step2_controller.js index 435fe0f..4663423 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step2_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step2_controller.js @@ -54,9 +54,8 @@ App.HighAvailabilityWizardStep2Controller = Em.Controller.extend(App.BlueprintMi }, showHideJournalNodesAddRemoveControl: function() { - var masterComponents = this.get('selectedServicesMasters'); - var jns = masterComponents.filterProperty('component_name', 'JOURNALNODE'); - var maxNumMasters = this.getMaxNumberOfMasters('JOURNALNODE') + var jns = this.get('selectedServicesMasters').filterProperty('component_name', 'JOURNALNODE'); + var maxNumMasters = this.getMaxNumberOfMasters('JOURNALNODE'); var showRemoveControl = jns.get('length') > this.get('JOURNALNODES_COUNT_MINIMUM'); var showAddControl = jns.get('length') < maxNumMasters; jns.forEach(function(item) { http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step3_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step3_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step3_controller.js index 0a46af7..f0f4f95 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step3_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step3_controller.js @@ -38,6 +38,7 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ haConfig: $.extend(true, {}, require('data/configs/wizards/ha_properties').haConfig), once: false, isLoaded: false, + isNextDisabled: Em.computed.not('isLoaded'), versionLoaded: true, hideDependenciesInfoBar: true, @@ -60,7 +61,7 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ }, loadConfigsTags: function () { - App.ajax.send({ + return App.ajax.send({ name: 'config.tags', sender: this, success: 'onLoadConfigsTags', @@ -221,8 +222,8 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ }, onLoadConfigs: function (data) { - this.set('serverConfigData',data); - this.removeConfigs(this.get('configsToRemove'), this.get('serverConfigData')); + this.set('serverConfigData', data); + this.removeConfigs(this.get('configsToRemove'), data); this.tweakServiceConfigs(this.get('haConfig.configs')); this.renderServiceConfigs(this.get('haConfig')); this.set('isLoaded', true); @@ -240,8 +241,8 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ var configsFromServer = this.get('serverConfigData.items'); ret.namespaceId = this.get('content.nameServiceId'); ret.serverConfigs = configsFromServer; - var hdfsConfigs = configsFromServer.findProperty('type','hdfs-site').properties; - var zkConfigs = configsFromServer.findProperty('type','zoo.cfg').properties; + var hdfsConfigs = configsFromServer.findProperty('type', 'hdfs-site').properties; + var zkConfigs = configsFromServer.findProperty('type', 'zoo.cfg').properties; var dfsHttpA = hdfsConfigs['dfs.namenode.http-address']; ret.nnHttpPort = dfsHttpA ? dfsHttpA.split(':')[1] : 50070; @@ -271,7 +272,7 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ return localDB; }, - tweakServiceConfigs: function(configs) { + tweakServiceConfigs: function (configs) { var localDB = this._prepareLocalDB(); var dependencies = this._prepareDependencies(); @@ -289,8 +290,8 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ * @param configs - configuration object * @returns {Object} */ - removeConfigs:function (configsToRemove, configs) { - Em.keys(configsToRemove).forEach(function(site){ + removeConfigs: function (configsToRemove, configs) { + Em.keys(configsToRemove).forEach(function (site) { var siteConfigs = configs.items.findProperty('type', site); if (siteConfigs) { configsToRemove[site].forEach(function (property) { @@ -320,7 +321,7 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ this.get('stepConfigs').pushObject(serviceConfig); this.set('selectedService', this.get('stepConfigs').objectAt(0)); - this.once = true; + this.set('once', true); }, /** @@ -334,8 +335,5 @@ App.HighAvailabilityWizardStep3Controller = Em.Controller.extend({ componentConfig.configs.pushObject(serviceConfigProperty); serviceConfigProperty.set('isEditable', serviceConfigProperty.get('isReconfigurable')); }, this); - }, - - isNextDisabled: Em.computed.not('isLoaded') - + } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step4_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step4_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step4_controller.js index c0f688e..5cf3880 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step4_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step4_controller.js @@ -31,8 +31,10 @@ App.HighAvailabilityWizardStep4Controller = Em.Controller.extend({ isNameNodeStarted: true, pullCheckPointStatus: function () { - var hostName = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').findProperty('isInstalled', true).hostName; - App.ajax.send({ + var hostName = this.get('content.masterComponentHosts') + .filterProperty('component', 'NAMENODE') + .findProperty('isInstalled', true).hostName; + return App.ajax.send({ name: 'admin.high_availability.getNnCheckPointStatus', sender: this, data: { http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step5_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step5_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step5_controller.js index 7b20439..8e035e8 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step5_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step5_controller.js @@ -44,7 +44,7 @@ App.HighAvailabilityWizardStep5Controller = App.HighAvailabilityProgressPageCont disableSNameNode: function () { var hostName = this.get('content.masterComponentHosts').findProperty('component', 'SECONDARY_NAMENODE').hostName; - App.ajax.send({ + return App.ajax.send({ name: 'common.host.host_component.passive', sender: this, data: { @@ -71,7 +71,22 @@ App.HighAvailabilityWizardStep5Controller = App.HighAvailabilityProgressPageCont * @param {Object} data - config object to update */ updateConfigProperties: function(data) { - var siteNames = ['hdfs-site','core-site']; + var siteNames = ['hdfs-site', 'core-site'].concat(this.getRangerSiteNames(data)); + var note = Em.I18n.t('admin.highAvailability.step4.save.configuration.note').format(App.format.role('NAMENODE', false)); + var configData = this.reconfigureSites(siteNames, data, note); + return App.ajax.send({ + name: 'common.service.configurations', + sender: this, + data: { + desired_config: configData + }, + error: 'onTaskError', + success: 'installHDFSClients' + }); + }, + + getRangerSiteNames: function(data) { + var siteNames = []; if (App.Service.find().someProperty('serviceName', 'RANGER')) { var hdfsPluginConfig = data.items.findProperty('type', 'ranger-hdfs-plugin-properties'); if (hdfsPluginConfig) { @@ -86,16 +101,7 @@ App.HighAvailabilityWizardStep5Controller = App.HighAvailabilityProgressPageCont } } } - var configData = this.reconfigureSites(siteNames, data, Em.I18n.t('admin.highAvailability.step4.save.configuration.note').format(App.format.role('NAMENODE', false))); - App.ajax.send({ - name: 'common.service.configurations', - sender: this, - data: { - desired_config: configData - }, - error: 'onTaskError', - success: 'installHDFSClients' - }); + return siteNames; }, installHDFSClients: function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step6_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step6_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step6_controller.js index 0ef3048..1240576 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step6_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step6_controller.js @@ -24,6 +24,8 @@ App.HighAvailabilityWizardStep6Controller = Em.Controller.extend({ POLL_INTERVAL: 1000, + MINIMAL_JOURNALNODE_COUNT: 3, + /** * Define whether next button should be enabled * @type {Boolean} @@ -74,7 +76,7 @@ App.HighAvailabilityWizardStep6Controller = Em.Controller.extend({ }, pullEachJnStatus: function (hostName) { - App.ajax.send({ + return App.ajax.send({ name: 'admin.high_availability.getJnCheckPointStatus', sender: this, data: { @@ -85,7 +87,6 @@ App.HighAvailabilityWizardStep6Controller = Em.Controller.extend({ }, checkJnCheckPointStatus: function (data) { - var self = this; var journalStatusInfo; var initJnCounter = 0; @@ -98,20 +99,25 @@ App.HighAvailabilityWizardStep6Controller = Em.Controller.extend({ this.set('hasStoppedJNs', true); } - if (this.incrementProperty('requestsCounter') === 3) { - if (initJnCounter === 3) { - this.set('status', 'done'); - this.set('isNextEnabled', true); + if (this.incrementProperty('requestsCounter') === this.MINIMAL_JOURNALNODE_COUNT) { + this.resolveJnCheckPointStatus(initJnCounter); + } + }, + + resolveJnCheckPointStatus: function(initJnCounter) { + var self = this; + if (initJnCounter === this.MINIMAL_JOURNALNODE_COUNT) { + this.set('status', 'done'); + this.set('isNextEnabled', true); + } else { + if (this.get('hasStoppedJNs')) { + this.set('status', 'journalnode_stopped') } else { - if (this.get('hasStoppedJNs')) { - this.set('status', 'journalnode_stopped') - } else { - this.set('status', 'waiting'); - } - window.setTimeout(function () { - self.pullCheckPointStatus(); - }, self.POLL_INTERVAL); + this.set('status', 'waiting'); } + window.setTimeout(function () { + self.pullCheckPointStatus(); + }, self.POLL_INTERVAL); } }, http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step9_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step9_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step9_controller.js index b98c2df..5dd419b 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step9_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/nameNode/step9_controller.js @@ -63,13 +63,13 @@ App.HighAvailabilityWizardStep9Controller = App.HighAvailabilityProgressPageCont }, installZKFC: function () { - var hostName = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').mapProperty('hostName'); - this.createInstallComponentTask('ZKFC', hostName, "HDFS"); + var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').mapProperty('hostName'); + this.createInstallComponentTask('ZKFC', hostNames, "HDFS"); }, startZKFC: function () { - var hostName = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').mapProperty('hostName'); - this.updateComponent('ZKFC', hostName, "HDFS", "Start"); + var hostNames = this.get('content.masterComponentHosts').filterProperty('component', 'NAMENODE').mapProperty('hostName'); + this.updateComponent('ZKFC', hostNames, "HDFS", "Start"); }, isPxfComponentInstalled: function () { @@ -235,6 +235,25 @@ App.HighAvailabilityWizardStep9Controller = App.HighAvailabilityProgressPageCont }); }, + /** + * + * @param {array} siteNames + * @param {object} data + */ + saveReconfiguredConfigs: function(siteNames, data) { + var note = Em.I18n.t('admin.highAvailability.step4.save.configuration.note').format(App.format.role('NAMENODE', false)); + var configData = this.reconfigureSites(siteNames, data, note); + return App.ajax.send({ + name: 'common.service.configurations', + sender: this, + data: { + desired_config: configData + }, + success: 'saveConfigTag', + error: 'onTaskError' + }); + }, + reconfigureHBase: function () { var data = this.get('content.serviceConfigProperties'); var siteNames = ['hbase-site']; @@ -252,58 +271,19 @@ App.HighAvailabilityWizardStep9Controller = App.HighAvailabilityProgressPageCont } } } - var configData = this.reconfigureSites(siteNames, data, Em.I18n.t('admin.highAvailability.step4.save.configuration.note').format(App.format.role('NAMENODE', false))); - App.ajax.send({ - name: 'common.service.configurations', - sender: this, - data: { - desired_config: configData - }, - success: 'saveConfigTag', - error: 'onTaskError' - }); + this.saveReconfiguredConfigs(siteNames, data); }, reconfigureAMS: function () { - var data = this.get('content.serviceConfigProperties'); - var configData = this.reconfigureSites(['ams-hbase-site'], data, Em.I18n.t('admin.highAvailability.step4.save.configuration.note').format(App.format.role('NAMENODE', false))); - App.ajax.send({ - name: 'common.service.configurations', - sender: this, - data: { - desired_config: configData - }, - success: 'saveConfigTag', - error: 'onTaskError' - }); + this.saveReconfiguredConfigs(['ams-hbase-site'], this.get('content.serviceConfigProperties')); }, reconfigureAccumulo: function () { - var data = this.get('content.serviceConfigProperties'); - var configData = this.reconfigureSites(['accumulo-site'], data, Em.I18n.t('admin.highAvailability.step4.save.configuration.note').format(App.format.role('NAMENODE', false))); - App.ajax.send({ - name: 'common.service.configurations', - sender: this, - data: { - desired_config: configData - }, - success: 'saveConfigTag', - error: 'onTaskError' - }); + this.saveReconfiguredConfigs(['accumulo-site'], this.get('content.serviceConfigProperties')); }, reconfigureHawq: function () { - var data = this.get('content.serviceConfigProperties'); - var configData = this.reconfigureSites(['hawq-site', 'hdfs-client'], data, Em.I18n.t('admin.highAvailability.step4.save.configuration.note').format(App.format.role('NAMENODE', false))); - App.ajax.send({ - name: 'common.service.configurations', - sender: this, - data: { - desired_config: configData - }, - success: 'saveConfigTag', - error: 'onTaskError' - }); + this.saveReconfiguredConfigs(['hawq-site', 'hdfs-client'], this.get('content.serviceConfigProperties')); }, saveConfigTag: function () { @@ -326,7 +306,7 @@ App.HighAvailabilityWizardStep9Controller = App.HighAvailabilityProgressPageCont deleteSNameNode: function () { var hostName = this.get('content.masterComponentHosts').findProperty('component', 'SECONDARY_NAMENODE').hostName; - App.ajax.send({ + return App.ajax.send({ name: 'common.delete.host_component', sender: this, data: { http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step1_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step1_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step1_controller_test.js new file mode 100644 index 0000000..3be1761 --- /dev/null +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step1_controller_test.js @@ -0,0 +1,132 @@ +/** + * 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'); + +describe('App.HighAvailabilityWizardStep1Controller', function () { + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep1Controller.create({ + content: Em.Object.create() + }); + }); + + describe('#isNameServiceIdValid', function () { + + var testCases = [ + { + input: '', + expected: false + }, + { + input: ' ', + expected: false + }, + { + input: ' a', + expected: false + }, + { + input: 'a ', + expected: false + }, + { + input: '%', + expected: false + }, + { + input: 'a', + expected: true + }, + { + input: 'A', + expected: true + }, + { + input: '1', + expected: true + }, + { + input: '123456789012345678901234567890123456789012345678901234567891234', + expected: true + }, + { + input: '1234567890123456789012345678901234567890123456789012345678912345', + expected: false + } + ]; + + testCases.forEach(function(test) { + it('should return ' + test.expected + + ' when nameServiceId=' + test.input, function() { + controller.set('content.nameServiceId', test.input); + expect(controller.get('isNameServiceIdValid')).to.be.equal(test.expected) + }); + }); + }); + + describe('#setHawqInstalled', function() { + + beforeEach(function() { + this.mock = sinon.stub(App.Service, 'find'); + }); + + afterEach(function() { + this.mock.restore(); + }); + + it('should set isHawqInstalled to true', function() { + this.mock.returns([{serviceName: 'HAWQ'}]); + controller.setHawqInstalled(); + expect(controller.get('isHawqInstalled')).to.be.true; + }); + + it('should set isHawqInstalled to false', function() { + this.mock.returns([]); + controller.setHawqInstalled(); + expect(controller.get('isHawqInstalled')).to.be.false; + }); + }); + + describe('#next', function() { + + beforeEach(function () { + sinon.stub(App.router, 'send'); + }); + afterEach(function () { + App.router.send.restore(); + }); + + it('App.router.send should be called', function() { + controller.reopen({ + isNameServiceIdValid: true + }); + controller.next(); + expect(App.router.send.calledOnce).to.be.true; + }); + + it('App.router.send should not be called', function() { + controller.reopen({ + isNameServiceIdValid: false + }); + controller.next(); + expect(App.router.send.called).to.be.false; + }); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step2_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step2_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step2_controller_test.js index 570f45a..d2cc36d 100644 --- a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step2_controller_test.js +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step2_controller_test.js @@ -25,7 +25,15 @@ function O (fl) { } describe('App.HighAvailabilityWizardStep2Controller', function () { - var controller = App.HighAvailabilityWizardStep2Controller.create(); + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep2Controller.create({ + addNewMasters: Em.K, + getMaxNumberOfMasters: Em.K, + selectedServicesMasters:[] + }); + }); describe('#sortMasterComponents', function () { @@ -36,4 +44,80 @@ describe('App.HighAvailabilityWizardStep2Controller', function () { }); }); + describe('#renderComponents', function() { + beforeEach(function() { + sinon.stub(controller, 'showHideJournalNodesAddRemoveControl'); + }); + afterEach(function() { + controller.showHideJournalNodesAddRemoveControl.restore(); + }); + + it('showHideJournalNodesAddRemoveControl should be called', function() { + controller.renderComponents([]); + expect(controller.showHideJournalNodesAddRemoveControl.calledOnce).to.be.true; + }); + }); + + describe('#addComponent', function() { + beforeEach(function() { + sinon.stub(controller, 'showHideJournalNodesAddRemoveControl'); + }); + afterEach(function() { + controller.showHideJournalNodesAddRemoveControl.restore(); + }); + + it('showHideJournalNodesAddRemoveControl should be called', function() { + controller.addComponent('C1'); + expect(controller.showHideJournalNodesAddRemoveControl.calledOnce).to.be.true; + }); + }); + + describe('#removeComponent', function() { + beforeEach(function() { + sinon.stub(controller, 'showHideJournalNodesAddRemoveControl'); + }); + afterEach(function() { + controller.showHideJournalNodesAddRemoveControl.restore(); + }); + + it('showHideJournalNodesAddRemoveControl should be called', function() { + controller.removeComponent('C1', 'id'); + expect(controller.showHideJournalNodesAddRemoveControl.calledOnce).to.be.true; + }); + }); + + describe('#showHideJournalNodesAddRemoveControl', function() { + beforeEach(function() { + sinon.stub(controller, 'getMaxNumberOfMasters').returns(3); + }); + afterEach(function() { + controller.getMaxNumberOfMasters.restore(); + }); + + it('should manage Journal Node controls', function() { + var selectedServicesMasters = Em.A([ + Em.Object.create({ + component_name: 'JOURNALNODE' + }), + Em.Object.create({ + component_name: 'JOURNALNODE' + }) + ]); + controller.set('selectedServicesMasters', selectedServicesMasters); + controller.showHideJournalNodesAddRemoveControl(); + expect(JSON.stringify(controller.get('selectedServicesMasters'))).to.be.eql(JSON.stringify(Em.A([ + Em.Object.create({ + component_name: 'JOURNALNODE', + showAddControl: false, + showRemoveControl: false + }), + Em.Object.create({ + component_name: 'JOURNALNODE', + showAddControl: true, + showRemoveControl: false + }) + ]))) + }); + }); + }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step3_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step3_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step3_controller_test.js index 98d71da..6bc8821 100644 --- a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step3_controller_test.js +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step3_controller_test.js @@ -74,8 +74,9 @@ describe('App.HighAvailabilityWizardStep3Controller', function() { }; beforeEach(function () { - controller = App.HighAvailabilityWizardStep3Controller.create(); - controller.set('serverConfigData', serverConfigData); + controller = App.HighAvailabilityWizardStep3Controller.create({ + serverConfigData: serverConfigData + }); }); afterEach(function () { @@ -454,5 +455,209 @@ describe('App.HighAvailabilityWizardStep3Controller', function() { }); + describe('#clearStep', function() { + + it('should clean data', function() { + controller.set('stepConfigs', [{}]); + controller.set('serverConfigData', {a: 1}); + controller.clearStep(); + expect(controller.get('stepConfigs')).to.be.empty; + expect(controller.get('serverConfigData')).to.be.empty; + }); + }); + + describe('#loadStep', function() { + beforeEach(function() { + sinon.stub(controller, 'clearStep'); + sinon.stub(controller, 'loadConfigsTags'); + controller.loadStep(); + }); + afterEach(function() { + controller.clearStep.restore(); + controller.loadConfigsTags.restore(); + }); + + it('loadConfigsTags should be called', function() { + expect(controller.loadConfigsTags.calledOnce).to.be.true; + }); + + it('clearStep should be called', function() { + expect(controller.clearStep.calledOnce).to.be.true; + }); + }); + + describe('#loadConfigsTags', function() { + it('App.ajax.send should be called', function() { + controller.loadConfigsTags(); + expect(testHelpers.findAjaxRequest('name', 'config.tags')).to.be.exist; + }); + }); + + describe('#onLoadConfigs', function() { + beforeEach(function() { + sinon.stub(controller, 'removeConfigs'); + sinon.stub(controller, 'tweakServiceConfigs'); + sinon.stub(controller, 'renderServiceConfigs'); + controller.set('configsToRemove', [{}]); + controller.set('haConfig', Em.Object.create({ + configs: [] + })); + controller.onLoadConfigs({a: 1}); + }); + afterEach(function() { + controller.tweakServiceConfigs.restore(); + controller.removeConfigs.restore(); + controller.renderServiceConfigs.restore(); + }); + + it('serviceConfigData should be set', function() { + expect(controller.get('serverConfigData')).to.be.eql({a: 1}); + }); + + it('removeConfigs should be called', function() { + expect(controller.removeConfigs.calledWith([{}], {a: 1})).to.be.true; + }); + + it('tweakServiceConfigs should be called', function() { + expect(controller.tweakServiceConfigs.calledWith([])).to.be.true; + }); + + it('renderServiceConfigs should be called', function() { + expect(controller.renderServiceConfigs.calledWith(Em.Object.create({ + configs: [] + }))).to.be.true; + }); + + it('isLoaded should be true', function() { + expect(controller.get('isLoaded')).to.be.true; + }); + }); + + describe('#renderServiceConfigs', function() { + var serviceConfig = { + serviceName: 'S1', + displayName: 's1', + configCategories: [ + { + name: 'C1' + }, + { + name: 'C2' + } + ] + }; + beforeEach(function() { + sinon.stub(controller, 'loadComponentConfigs'); + sinon.stub(App.Service, 'find').returns([Em.Object.create({serviceName: 'C1'})]); + + controller.renderServiceConfigs(serviceConfig); + }); + afterEach(function() { + controller.loadComponentConfigs.restore(); + App.Service.find.restore(); + }); + + it('serviceConfig should be pushed in stepConfigs', function() { + expect(controller.get('stepConfigs')).to.have.length(1); + }); + + it('selectedService should be set', function() { + expect(JSON.stringify(controller.get('selectedService'))).to.be.equal(JSON.stringify(App.ServiceConfig.create({ + serviceName: 'S1', + displayName: 's1', + configCategories: [{ + name: 'C1' + }], + showConfig: true, + configs: [] + }))); + }); + + it('once should be true', function() { + expect(controller.get('once')).to.be.true; + }); + }); + + describe('#loadComponentConfigs', function() { + + it('should push configs', function() { + var _componentConfig = { + configs: [{ + isReconfigurable: true + }] + }; + var componentConfig = { + configs: [] + }; + controller.loadComponentConfigs(_componentConfig, componentConfig); + expect(componentConfig.configs).to.have.length(1); + expect(componentConfig.configs[0].get('isEditable')).to.be.true; + }); + }); + + describe('#_prepareLocalDB', function() { + beforeEach(function() { + sinon.stub(App.Service, 'find').returns([{serviceName: 'S1'}]); + }); + afterEach(function() { + App.Service.find.restore(); + }); + + it('should return localDb object', function() { + controller.set('content', Em.Object.create({ + masterComponentHosts: [{}], + slaveComponentHosts: [{}], + hosts: [{}] + })); + expect(controller._prepareLocalDB()).to.be.eql({ + masterComponentHosts: [{}], + slaveComponentHosts: [{}], + hosts: [{}], + installedServices: ['S1'] + }); + }); + }); + + describe('#tweakServiceConfigs', function() { + beforeEach(function() { + sinon.stub(controller, '_prepareLocalDB'); + sinon.stub(controller, '_prepareDependencies'); + sinon.stub(App.NnHaConfigInitializer, 'initialValue'); + }); + afterEach(function() { + controller._prepareLocalDB.restore(); + controller._prepareDependencies.restore(); + App.NnHaConfigInitializer.initialValue.restore(); + }); + + it('should modify configs', function() { + expect(controller.tweakServiceConfigs([{}])).to.be.eql([{isOverridable: false}]); + }); + }); + + describe('#removeConfigs', function() { + + it('should remove config properties', function() { + var configs = { + items: [ + { + type: 'k1', + properties: { + p1: {} + } + } + ] + }; + expect(JSON.stringify(controller.removeConfigs({k1: ['p1']}, configs))).to.be.equal(JSON.stringify({ + items: [ + { + type: 'k1', + properties: {} + } + ] + })); + }); + }); + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step4_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step4_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step4_controller_test.js index d5ab8d2..e850339 100644 --- a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step4_controller_test.js +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step4_controller_test.js @@ -17,19 +17,27 @@ */ var App = require('app'); +var testHelpers = require('test/helpers'); + describe('App.HighAvailabilityWizardStep4Controller', function() { + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep4Controller.create({ + content: Em.Object.create() + }); + }); describe('#checkNnCheckPointStatus', function() { beforeEach(function() { - this.controller = App.HighAvailabilityWizardStep4Controller.create(); this.clock = sinon.useFakeTimers(); - sinon.stub(this.controller, 'pullCheckPointStatus'); + sinon.stub(controller, 'pullCheckPointStatus'); }); afterEach(function() { this.clock.restore(); - this.controller.pullCheckPointStatus.restore(); + controller.pullCheckPointStatus.restore(); }); var tests = [ @@ -95,21 +103,75 @@ describe('App.HighAvailabilityWizardStep4Controller', function() { describe(test.m, function() { beforeEach(function () { - this.controller.set('isNameNodeStarted', !test.e.isNameNodeStarted); - this.controller.checkNnCheckPointStatus(test.responseData); - this.clock.tick(this.controller.get('POLL_INTERVAL')); + controller.set('isNameNodeStarted', !test.e.isNameNodeStarted); + controller.checkNnCheckPointStatus(test.responseData); + this.clock.tick(controller.get('POLL_INTERVAL')); }); it('isNameNodeStarted is ' + test.e.isNameNodeStarted, function () { - expect(this.controller.get('isNameNodeStarted')).to.be.equal(test.e.isNameNodeStarted); + expect(controller.get('isNameNodeStarted')).to.be.equal(test.e.isNameNodeStarted); }); it('isNextEnabled is ' + test.e.isNextEnabled, function () { - expect(this.controller.get('isNextEnabled')).to.be.equal(test.e.isNextEnabled); + expect(controller.get('isNextEnabled')).to.be.equal(test.e.isNextEnabled); }); it('pullCheckPointStatus is ' + (test.e.isPollingCalled ? '' : 'not') + ' called', function () { - expect(this.controller.pullCheckPointStatus.called).to.be.equal(test.e.isPollingCalled); + expect(controller.pullCheckPointStatus.called).to.be.equal(test.e.isPollingCalled); }); }); }); }); + + describe('#pullCheckPointStatus', function() { + + it('App.ajax.send should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'NAMENODE', + isInstalled: true, + hostName: 'host1' + } + ]); + controller.pullCheckPointStatus(); + var args = testHelpers.findAjaxRequest('name', 'admin.high_availability.getNnCheckPointStatus'); + expect(args[0]).to.be.eql({ + name: 'admin.high_availability.getNnCheckPointStatus', + sender: controller, + data: { + hostName: 'host1' + }, + success: 'checkNnCheckPointStatus' + }); + }); + }); + + describe('#done', function() { + var mock = { + getKDCSessionState: Em.clb + }; + + beforeEach(function() { + sinon.spy(mock, 'getKDCSessionState'); + sinon.stub(App, 'get').returns(mock); + sinon.stub(App.router, 'send'); + }); + afterEach(function() { + App.get.restore(); + App.router.send.restore(); + mock.getKDCSessionState.restore(); + }); + + it('App.router.send should not be called', function() { + controller.set('isNextEnabled', false); + controller.done(); + expect(mock.getKDCSessionState.called).to.be.false; + expect(App.router.send.called).to.be.false; + }); + + it('App.router.send should be called', function() { + controller.set('isNextEnabled', true); + controller.done(); + expect(mock.getKDCSessionState.calledOnce).to.be.true; + expect(App.router.send.calledOnce).to.be.true; + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step5_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step5_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step5_controller_test.js new file mode 100644 index 0000000..ecc513d --- /dev/null +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step5_controller_test.js @@ -0,0 +1,312 @@ +/** + * 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'); +var testHelpers = require('test/helpers'); + + +describe('App.HighAvailabilityWizardStep5Controller', function() { + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep5Controller.create({ + content: Em.Object.create() + }); + }); + + describe('#installNameNode', function() { + beforeEach(function() { + sinon.stub(controller, 'createInstallComponentTask'); + }); + afterEach(function() { + controller.createInstallComponentTask.restore(); + }); + + it('createInstallComponentTask should be called', function() { + controller.set('content.masterComponentHosts', [{ + component: 'NAMENODE', + isInstalled: false, + hostName: 'host1' + }]); + controller.installNameNode(); + expect(controller.createInstallComponentTask.calledWith('NAMENODE', 'host1', 'HDFS')).to.be.true; + }); + }); + + describe('#installJournalNodes', function() { + beforeEach(function() { + sinon.stub(controller, 'createInstallComponentTask'); + }); + afterEach(function() { + controller.createInstallComponentTask.restore(); + }); + + it('createInstallComponentTask should be called', function() { + controller.set('content.masterComponentHosts', [{ + component: 'JOURNALNODE', + hostName: 'host1' + }]); + controller.installJournalNodes(); + expect(controller.createInstallComponentTask.calledWith('JOURNALNODE', ['host1'], 'HDFS')).to.be.true; + }); + }); + + describe('#startJournalNodes', function() { + beforeEach(function() { + sinon.stub(controller, 'updateComponent'); + }); + afterEach(function() { + controller.updateComponent.restore(); + }); + + it('updateComponent should be called', function() { + controller.set('content.masterComponentHosts', [{ + component: 'JOURNALNODE', + hostName: 'host1' + }]); + controller.startJournalNodes(); + expect(controller.updateComponent.calledWith('JOURNALNODE', ['host1'], 'HDFS', 'Start')).to.be.true; + }); + }); + + describe('#disableSNameNode', function() { + + it('App.ajax.send should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'SECONDARY_NAMENODE', + hostName: 'host1' + } + ]); + controller.disableSNameNode(); + var args = testHelpers.findAjaxRequest('name', 'common.host.host_component.passive'); + expect(args[0]).to.be.eql({ + name: 'common.host.host_component.passive', + sender: controller, + data: { + hostName: 'host1', + passive_state: "ON", + componentName: 'SECONDARY_NAMENODE' + }, + success: 'onTaskCompleted', + error: 'onTaskError' + }); + }); + }); + + describe('#reconfigureHDFS', function() { + beforeEach(function() { + sinon.stub(controller, 'reconfigureSecureHDFS'); + sinon.stub(controller, 'updateConfigProperties'); + }); + afterEach(function() { + controller.reconfigureSecureHDFS.restore(); + controller.updateConfigProperties.restore(); + App.set('isKerberosEnabled', false); + }); + + it('reconfigureSecureHDFS should be called', function() { + App.set('isKerberosEnabled', true); + controller.reconfigureHDFS(); + expect(controller.reconfigureSecureHDFS.calledOnce).to.be.true; + expect(controller.updateConfigProperties.called).to.be.false; + }); + + it('updateConfigProperties should be called', function() { + controller.set('content.serviceConfigProperties', {}); + controller.reconfigureHDFS(); + expect(controller.reconfigureSecureHDFS.called).to.be.false; + expect(controller.updateConfigProperties.calledWith({})).to.be.true; + }); + }); + + describe('#updateConfigProperties', function() { + beforeEach(function() { + sinon.stub(controller, 'reconfigureSites').returns({}); + }); + afterEach(function() { + controller.reconfigureSites.restore(); + }); + + it('App.ajax.send should be called', function() { + controller.updateConfigProperties({}); + var args = testHelpers.findAjaxRequest('name', 'common.service.configurations'); + expect(args[0]).to.be.eql({ + name: 'common.service.configurations', + sender: controller, + data: { + desired_config: {} + }, + error: 'onTaskError', + success: 'installHDFSClients' + }); + }); + }); + + describe('#getRangerSiteNames', function() { + beforeEach(function() { + sinon.stub(App.Service, 'find').returns([{serviceName: 'RANGER'}]); + }); + afterEach(function() { + App.Service.find.restore(); + }); + + it('should return Ranger site names', function() { + var data = { + items: [ + { + type: 'ranger-hdfs-plugin-properties', + properties: { + 'xasecure.audit.destination.hdfs.dir': 'foo' + } + }, + { + type: 'ranger-hdfs-audit', + properties: { + 'xasecure.audit.destination.hdfs.dir': 'foo' + } + } + ] + }; + expect(controller.getRangerSiteNames(data)).to.be.eql([ + 'ranger-hdfs-plugin-properties', + 'ranger-hdfs-audit' + ]); + }); + }); + + describe('#installHDFSClients', function() { + var mock = { + saveHdfsClientHosts: sinon.spy() + }; + beforeEach(function() { + sinon.stub(controller, 'createInstallComponentTask'); + sinon.stub(App.router, 'get').returns(mock); + sinon.stub(App.clusterStatus, 'setClusterStatus'); + controller.set('content.masterComponentHosts', [ + Em.Object.create({ + component: 'NAMENODE', + hostName: 'host1' + }), + Em.Object.create({ + component: 'JOURNALNODE', + hostName: 'host2' + }) + ]); + controller.installHDFSClients(); + }); + afterEach(function() { + controller.createInstallComponentTask.restore(); + App.router.get.restore(); + App.clusterStatus.setClusterStatus.restore(); + }); + + it('createInstallComponentTask should be called', function() { + expect(controller.createInstallComponentTask.calledWith('HDFS_CLIENT', ['host1', 'host2'], 'HDFS')).to.be.true; + }); + + it('saveHdfsClientHosts should be called', function() { + expect(mock.saveHdfsClientHosts.calledWith(['host1', 'host2'])).to.be.true; + }); + + it('setClusterStatus should be called', function() { + expect(App.clusterStatus.setClusterStatus.calledOnce).to.be.true; + }); + }); + + describe('#reconfigureSecureHDFS', function() { + var mock = { + loadConfigsTags: sinon.spy() + }; + beforeEach(function() { + sinon.stub(App.router, 'get').returns(mock); + }); + afterEach(function() { + App.router.get.restore(); + }); + + it('loadConfigsTags should be called', function() { + controller.reconfigureSecureHDFS(); + expect(mock.loadConfigsTags.calledOnce).to.be.true; + }); + }); + + describe('#onLoadConfigsTags', function() { + var mock = { + onLoadConfigsTags: sinon.spy() + }; + beforeEach(function() { + sinon.stub(App.router, 'get').returns(mock); + }); + afterEach(function() { + App.router.get.restore(); + }); + + it('onLoadConfigsTags should be called', function() { + controller.onLoadConfigsTags({}); + expect(mock.onLoadConfigsTags.calledWith({})).to.be.true; + }); + }); + + describe('#onLoadConfigs', function() { + var mock = Em.Object.create({ + removeConfigs: sinon.spy(), + configsToRemove: [{}] + }); + var data = { + items: [ + { + type: 't1', + properties: {} + } + ] + }; + beforeEach(function() { + sinon.stub(App.router, 'get').returns(mock); + sinon.stub(controller, 'updateConfigProperties'); + controller.set('content.serviceConfigProperties', { + items: [ + { + type: 't1', + properties: { + foo: 'bar' + } + } + ] + }); + controller.onLoadConfigs(data); + }); + afterEach(function() { + App.router.get.restore(); + controller.updateConfigProperties.restore(); + }); + + it('removeConfigs should be called', function() { + expect(mock.removeConfigs.calledWith([{}], {items: [{ + type: 't1', + properties: { + foo: 'bar' + } + }]})).to.be.true; + }); + + it('updateConfigProperties should be called', function() { + expect(controller.updateConfigProperties.calledOnce).to.be.true; + }); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step6_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step6_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step6_controller_test.js new file mode 100644 index 0000000..f66c4df --- /dev/null +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step6_controller_test.js @@ -0,0 +1,195 @@ +/** + * 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'); +var testHelpers = require('test/helpers'); + + +describe('App.HighAvailabilityWizardStep6Controller', function() { + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep6Controller.create({ + content: Em.Object.create() + }); + }); + + describe('#loadStep', function() { + beforeEach(function() { + sinon.stub(controller, 'pullCheckPointStatus'); + controller.loadStep(); + }); + afterEach(function() { + controller.pullCheckPointStatus.restore(); + }); + + it('status should be waiting', function() { + expect(controller.get('status')).to.be.equal('waiting'); + }); + + it('isNextEnabled should be false', function() { + expect(controller.get('isNextEnabled')).to.be.false; + }); + + it('pullCheckPointStatus should be called', function() { + expect(controller.pullCheckPointStatus.calledOnce).to.be.true; + }); + }); + + describe('#pullCheckPointStatus', function() { + beforeEach(function() { + sinon.stub(controller, 'pullEachJnStatus'); + controller.set('content.masterComponentHosts', [ + { + component: 'JOURNALNODE', + hostName: 'host1' + }, + { + component: 'JOURNALNODE', + hostName: 'host2' + } + ]); + controller.pullCheckPointStatus(); + }); + afterEach(function() { + controller.pullEachJnStatus.restore(); + }); + + it('initJnCounter should be 0', function() { + expect(controller.get('initJnCounter')).to.be.equal(0); + }); + + it('requestsCounter should be 0', function() { + expect(controller.get('requestsCounter')).to.be.equal(0); + }); + + it('hasStoppedJNs should be 0', function() { + expect(controller.get('hasStoppedJNs')).to.be.false; + }); + + it('pullEachJnStatus should be called', function() { + expect(controller.pullEachJnStatus.calledTwice).to.be.true; + }); + }); + + describe('#pullEachJnStatus', function() { + + it('App.ajax.send should be called', function() { + controller.pullEachJnStatus('host1'); + var args = testHelpers.findAjaxRequest('name', 'admin.high_availability.getJnCheckPointStatus'); + expect(args[0]).to.be.eql({ + name: 'admin.high_availability.getJnCheckPointStatus', + sender: controller, + data: { + hostName: 'host1' + }, + success: 'checkJnCheckPointStatus' + }); + }); + }); + + describe('#checkJnCheckPointStatus', function() { + beforeEach(function() { + sinon.stub(controller, 'resolveJnCheckPointStatus'); + }); + afterEach(function() { + controller.resolveJnCheckPointStatus.restore(); + }); + + it('should have stopped JournalNodes when metrics absent', function() { + controller.set('requestsCounter', 0); + controller.checkJnCheckPointStatus({}); + expect(controller.get('hasStoppedJNs')).to.be.true; + expect(controller.resolveJnCheckPointStatus.called).to.be.false; + }); + + it('should have init JournalNodes when metrics present', function() { + controller.set('requestsCounter', controller.MINIMAL_JOURNALNODE_COUNT - 1); + controller.set('content.nameServiceId', 'foo'); + controller.checkJnCheckPointStatus({ + metrics: { + dfs: { + journalnode: { + journalsStatus: JSON.stringify({foo: { + Formatted: 'true' + }}) + } + } + } + }); + expect(controller.get('hasStoppedJNs')).to.be.false; + expect(controller.get('initJnCounter')).to.be.equal(1); + expect(controller.resolveJnCheckPointStatus.calledWith(1)).to.be.true; + }); + }); + + describe('#resolveJnCheckPointStatus', function() { + beforeEach(function() { + sinon.stub(controller, 'pullCheckPointStatus'); + this.clock = sinon.useFakeTimers(); + }); + afterEach(function() { + controller.pullCheckPointStatus.restore(); + this.clock.restore(); + }); + + it('status should be done when all JournalNodes initialized', function() { + controller.resolveJnCheckPointStatus(controller.MINIMAL_JOURNALNODE_COUNT); + expect(controller.get('status')).to.be.equal('done'); + expect(controller.get('isNextEnabled')).to.be.true; + }); + + it('status should be waiting when all JournalNodes waiting', function() { + controller.resolveJnCheckPointStatus(1); + expect(controller.get('status')).to.be.equal('waiting'); + expect(controller.get('isNextEnabled')).to.be.false; + this.clock.tick(controller.POLL_INTERVAL); + expect(controller.pullCheckPointStatus.calledOnce).to.be.true; + }); + + it('status should be journalnode_stopped when all JournalNodes stopped', function() { + controller.set('hasStoppedJNs', true); + controller.resolveJnCheckPointStatus(1); + expect(controller.get('status')).to.be.equal('journalnode_stopped'); + expect(controller.get('isNextEnabled')).to.be.false; + this.clock.tick(controller.POLL_INTERVAL); + expect(controller.pullCheckPointStatus.calledOnce).to.be.true; + }); + }); + + describe('#done', function() { + beforeEach(function() { + sinon.stub(App.router, 'send'); + }); + afterEach(function() { + App.router.send.restore(); + }); + + it('App.router.send should be called', function() { + controller.set('isNextEnabled', true); + controller.done(); + expect(App.router.send.calledWith('next')).to.be.true; + }); + + it('App.router.send should not be called', function() { + controller.set('isNextEnabled', false); + controller.done(); + expect(App.router.send.called).to.be.false; + }); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step7_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step7_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step7_controller_test.js new file mode 100644 index 0000000..d2b385a --- /dev/null +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step7_controller_test.js @@ -0,0 +1,122 @@ +/** + * 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'); +var testHelpers = require('test/helpers'); + + +describe('App.HighAvailabilityWizardStep7Controller', function() { + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep7Controller.create({ + content: Em.Object.create() + }); + }); + + describe('#initializeTasks', function() { + beforeEach(function() { + sinon.stub(controller, 'removeTasks'); + sinon.stub(App.Service, 'find').returns([]); + }); + afterEach(function() { + controller.removeTasks.restore(); + App.Service.find.restore(); + }); + + it('removeTasks should be called', function() { + controller.initializeTasks(); + expect(controller.removeTasks.calledWith(['startAmbariInfra', 'startRanger'])).to.be.true; + }); + }); + + describe('#startAmbariInfra', function() { + beforeEach(function() { + sinon.stub(controller, 'startServices'); + }); + afterEach(function() { + controller.startServices.restore(); + }); + + it('startServices should be called', function() { + controller.startAmbariInfra(); + expect(controller.startServices.calledWith(false, ['AMBARI_INFRA'], true)).to.be.true; + }); + }); + + describe('#startRanger', function() { + beforeEach(function() { + sinon.stub(controller, 'updateComponent'); + }); + afterEach(function() { + controller.updateComponent.restore(); + }); + + it('updateComponent should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'RANGER_ADMIN', + hostName: 'host1' + } + ]); + controller.startRanger(); + expect(controller.updateComponent.calledWith('RANGER_ADMIN', ['host1'], "RANGER", "Start")).to.be.true; + }); + }); + + describe('#startZooKeeperServers', function() { + beforeEach(function() { + sinon.stub(controller, 'updateComponent'); + }); + afterEach(function() { + controller.updateComponent.restore(); + }); + + it('updateComponent should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'ZOOKEEPER_SERVER', + hostName: 'host1' + } + ]); + controller.startZooKeeperServers(); + expect(controller.updateComponent.calledWith('ZOOKEEPER_SERVER', ['host1'], "ZOOKEEPER", "Start")).to.be.true; + }); + }); + + describe('#startNameNode', function() { + beforeEach(function() { + sinon.stub(controller, 'updateComponent'); + }); + afterEach(function() { + controller.updateComponent.restore(); + }); + + it('updateComponent should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'NAMENODE', + hostName: 'host1', + isInstalled: true + } + ]); + controller.startNameNode(); + expect(controller.updateComponent.calledWith('NAMENODE', 'host1', "HDFS", "Start")).to.be.true; + }); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step8_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step8_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step8_controller_test.js new file mode 100644 index 0000000..4af3aa9 --- /dev/null +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step8_controller_test.js @@ -0,0 +1,53 @@ +/** + * 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'); +var testHelpers = require('test/helpers'); + + +describe('App.HighAvailabilityWizardStep8Controller', function() { + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep8Controller.create({ + content: Em.Object.create() + }); + }); + + describe('#done', function() { + var mock = { + getKDCSessionState: Em.clb + }; + beforeEach(function() { + sinon.stub(App, 'get').returns(mock); + sinon.spy(mock, 'getKDCSessionState'); + sinon.stub(App.router, 'send'); + }); + afterEach(function() { + App.get.restore(); + mock.getKDCSessionState.restore(); + App.router.send.restore(); + }); + + it('App.router.send should be called', function() { + controller.done(); + expect(mock.getKDCSessionState.calledOnce).to.be.true; + expect(App.router.send.calledWith('next')).to.be.true; + }); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/b511b5b2/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step9_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step9_controller_test.js b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step9_controller_test.js new file mode 100644 index 0000000..246fa9e --- /dev/null +++ b/ambari-web/test/controllers/main/admin/highAvailability/nameNode/step9_controller_test.js @@ -0,0 +1,342 @@ +/** + * 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'); +var testHelpers = require('test/helpers'); + + +describe('App.HighAvailabilityWizardStep9Controller', function() { + var controller; + + beforeEach(function() { + controller = App.HighAvailabilityWizardStep9Controller.create({ + content: Em.Object.create() + }); + }); + + describe('#initializeTasks', function() { + beforeEach(function() { + sinon.stub(App.Service, 'find').returns([{ + serviceName: 'PXF' + }]); + sinon.stub(controller, 'isPxfComponentInstalled').returns(true); + sinon.stub(controller, 'removeTasks'); + controller.set('content.masterComponentHosts', [ + { + component: 'NAMENODE', + isInstalled: false, + hostName: 'host1' + } + ]); + }); + afterEach(function() { + App.Service.find.restore(); + controller.isPxfComponentInstalled.restore(); + controller.removeTasks.restore(); + }); + + it('removeTasks should be called', function() { + controller.initializeTasks(); + expect(controller.get('secondNameNodeHost')).to.be.equal('host1'); + expect(controller.removeTasks.calledWith([ + 'installPXF', + 'reconfigureRanger', + 'reconfigureHBase', + 'reconfigureAMS', + 'reconfigureAccumulo', + 'reconfigureHawq' + ])).to.be.true; + }); + }); + + describe('#startSecondNameNode', function() { + beforeEach(function() { + sinon.stub(controller, 'updateComponent'); + }); + afterEach(function() { + controller.updateComponent.restore(); + }); + + it('updateComponent should be called', function() { + controller.set('secondNameNodeHost', 'host1'); + controller.startSecondNameNode(); + expect(controller.updateComponent.calledWith('NAMENODE', 'host1', "HDFS", "Start")).to.be.true; + }); + }); + + describe('#installZKFC', function() { + beforeEach(function() { + sinon.stub(controller, 'createInstallComponentTask'); + }); + afterEach(function() { + controller.createInstallComponentTask.restore(); + }); + + it('createInstallComponentTask should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'NAMENODE', + hostName: 'host1' + } + ]); + controller.installZKFC(); + expect(controller.createInstallComponentTask.calledWith('ZKFC', ['host1'], "HDFS")).to.be.true; + }); + }); + + describe('#startZKFC', function() { + beforeEach(function() { + sinon.stub(controller, 'updateComponent'); + }); + afterEach(function() { + controller.updateComponent.restore(); + }); + + it('updateComponent should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'NAMENODE', + hostName: 'host1' + } + ]); + controller.startZKFC(); + expect(controller.updateComponent.calledWith('ZKFC', ['host1'], "HDFS", "Start")).to.be.true; + }); + }); + + describe('#isPxfComponentInstalled', function() { + beforeEach(function() { + this.mock = sinon.stub(controller, 'getSlaveComponentHosts'); + controller.set('secondNameNodeHost', 'host1'); + }); + afterEach(function() { + this.mock.restore(); + }); + + it('should return true', function() { + this.mock.returns([ + { + componentName: 'PXF', + hosts: [{ + hostName: 'host1' + }] + } + ]); + expect(controller.isPxfComponentInstalled()).to.be.true; + }); + + it('should return false', function() { + this.mock.returns([]); + expect(controller.isPxfComponentInstalled()).to.be.false; + }); + }); + + describe('#installPXF', function() { + beforeEach(function() { + sinon.stub(controller, 'createInstallComponentTask'); + }); + afterEach(function() { + controller.createInstallComponentTask.restore(); + }); + + it('createInstallComponentTask should be called', function() { + controller.set('secondNameNodeHost', 'host1'); + controller.installPXF(); + expect(controller.createInstallComponentTask.calledWith('PXF', 'host1', "PXF")).to.be.true; + }); + }); + + describe('#saveReconfiguredConfigs', function() { + beforeEach(function() { + sinon.stub(controller, 'reconfigureSites').returns({}); + }); + afterEach(function() { + controller.reconfigureSites.restore(); + }); + + it('App.ajax.send should be called', function() { + controller.saveReconfiguredConfigs(['site1'], {}); + var args = testHelpers.findAjaxRequest('name', 'common.service.configurations'); + expect(args[0]).to.be.eql({ + name: 'common.service.configurations', + sender: controller, + data: { + desired_config: {} + }, + success: 'saveConfigTag', + error: 'onTaskError' + }); + }); + }); + + describe('#reconfigureHBase', function() { + beforeEach(function() { + sinon.stub(App.Service, 'find').returns([ + { + serviceName: 'RANGER' + } + ]); + sinon.stub(controller, 'saveReconfiguredConfigs'); + }); + afterEach(function() { + App.Service.find.restore(); + controller.saveReconfiguredConfigs.restore(); + }); + + it('saveReconfiguredConfigs should be called', function() { + var data = { + items: [ + { + type: 'ranger-hbase-plugin-properties', + properties: { + 'xasecure.audit.destination.hdfs.dir': '' + } + }, + { + type: 'ranger-hbase-audit', + properties: { + 'xasecure.audit.destination.hdfs.dir': '' + } + } + ] + }; + controller.set('content.serviceConfigProperties', data); + controller.reconfigureHBase(); + expect(controller.saveReconfiguredConfigs.calledWith([ + 'hbase-site', 'ranger-hbase-plugin-properties', 'ranger-hbase-audit' + ], data)).to.be.true; + }); + }); + + describe('#reconfigureAMS', function() { + beforeEach(function() { + sinon.stub(controller, 'saveReconfiguredConfigs'); + }); + afterEach(function() { + controller.saveReconfiguredConfigs.restore(); + }); + + it('saveReconfiguredConfigs should be called', function() { + controller.set('content.serviceConfigProperties', {}); + controller.reconfigureAMS(); + expect(controller.saveReconfiguredConfigs.calledWith(['ams-hbase-site'], {})).to.be.true; + }); + }); + + describe('#reconfigureAccumulo', function() { + beforeEach(function() { + sinon.stub(controller, 'saveReconfiguredConfigs'); + }); + afterEach(function() { + controller.saveReconfiguredConfigs.restore(); + }); + + it('saveReconfiguredConfigs should be called', function() { + controller.set('content.serviceConfigProperties', {}); + controller.reconfigureAccumulo(); + expect(controller.saveReconfiguredConfigs.calledWith(['accumulo-site'], {})).to.be.true; + }); + }); + + describe('#reconfigureHawq', function() { + beforeEach(function() { + sinon.stub(controller, 'saveReconfiguredConfigs'); + }); + afterEach(function() { + controller.saveReconfiguredConfigs.restore(); + }); + + it('saveReconfiguredConfigs should be called', function() { + controller.set('content.serviceConfigProperties', {}); + controller.reconfigureHawq(); + expect(controller.saveReconfiguredConfigs.calledWith(['hawq-site', 'hdfs-client'], {})).to.be.true; + }); + }); + + describe('#saveConfigTag', function() { + beforeEach(function() { + sinon.stub(App.clusterStatus, 'setClusterStatus'); + sinon.stub(controller, 'onTaskCompleted'); + controller.saveConfigTag(); + }); + afterEach(function() { + App.clusterStatus.setClusterStatus.restore(); + controller.onTaskCompleted.restore(); + }); + + it('App.clusterStatus.setClusterStatus should be called', function() { + expect(App.clusterStatus.setClusterStatus.calledOnce).to.be.true; + }); + + it('onTaskCompleted should be called', function() { + expect(controller.onTaskCompleted.calledOnce).to.be.true; + }); + }); + + describe('#startAllServices', function() { + beforeEach(function() { + sinon.stub(controller, 'startServices'); + }); + afterEach(function() { + controller.startServices.restore(); + }); + + it('startServices should be called', function() { + controller.startAllServices(); + expect(controller.startServices.calledWith(false)).to.be.true; + }); + }); + + describe('#stopHDFS', function() { + beforeEach(function() { + sinon.stub(controller, 'stopServices'); + }); + afterEach(function() { + controller.stopServices.restore(); + }); + + it('stopServices should be called', function() { + controller.stopHDFS(); + expect(controller.stopServices.calledWith(['HDFS'], true)).to.be.true; + }); + }); + + describe('#deleteSNameNode', function() { + + it('App.ajax.send should be called', function() { + controller.set('content.masterComponentHosts', [ + { + component: 'SECONDARY_NAMENODE', + hostName: 'host1' + } + ]); + controller.deleteSNameNode(); + var args = testHelpers.findAjaxRequest('name', 'common.delete.host_component'); + expect(args[0]).to.be.eql({ + name: 'common.delete.host_component', + sender: controller, + data: { + componentName: 'SECONDARY_NAMENODE', + hostName: 'host1' + }, + success: 'onTaskCompleted', + error: 'onTaskError' + }); + }); + }); +});
