You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2012/09/17 19:17:16 UTC
svn commit: r1386725 - in /incubator/ambari/branches/AMBARI-666: ./
ambari-web/app/ ambari-web/app/controllers/installer/ ambari-web/app/utils/
ambari-web/test/installer/
Author: yusaku
Date: Mon Sep 17 17:17:16 2012
New Revision: 1386725
URL: http://svn.apache.org/viewvc?rev=1386725&view=rev
Log:
AMBARI-745. Add unit tests for Installer Step 1 (Welcome page). (yusaku)
Added:
incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step1_controller.js
incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step2_controller.js
Removed:
incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step1.js
incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step2.js
Modified:
incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt
incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js
incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js
incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step1_test.js
Modified: incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt?rev=1386725&r1=1386724&r2=1386725&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt (original)
+++ incubator/ambari/branches/AMBARI-666/AMBARI-666-CHANGES.txt Mon Sep 17 17:17:16 2012
@@ -12,6 +12,8 @@ AMBARI-666 branch (unreleased changes)
NEW FEATURES
+ AMBARI-745. Add unit tests for Installer Step 1 (Welcome page). (yusaku)
+
AMBARI-744. Add definition for service config properties. (yusaku)
AMBARI-743. Add unit testing framework for Ambari Web. (yusaku)
Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js?rev=1386725&r1=1386724&r2=1386725&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers.js Mon Sep 17 17:17:16 2012
@@ -22,8 +22,8 @@
require('controllers/application');
require('controllers/login_controller');
require('controllers/installer');
-require('controllers/installer/step1');
-require('controllers/installer/step2');
+require('controllers/installer/step1_controller');
+require('controllers/installer/step2_controller');
require('controllers/installer/step3');
require('controllers/installer/step7_controller');
require('controllers/main');
Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step1_controller.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step1_controller.js?rev=1386725&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step1_controller.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step1_controller.js Mon Sep 17 17:17:16 2012
@@ -0,0 +1,58 @@
+/**
+ * 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 db = require('utils/db');
+
+App.InstallerStep1Controller = Em.Controller.extend({
+ name: 'installerStep1Controller',
+ content: [],
+ clusterName: '',
+ invalidClusterName: false,
+ clusterNameError: '',
+
+ /**
+ * Returns true if the cluster name is valid and stores it in localStorage.
+ * Returns false otherwise, and sets appropriate field error message.
+ */
+ validateStep1: function () {
+ console.log('TRACE: Entering controller:InstallerStep1:validateStep1 function');
+ if (this.get('clusterName') == '') {
+ this.set('clusterNameError', Em.I18n.t('installer.step1.clusterName.error.required'));
+ this.set('invalidClusterName', true);
+ return false;
+ } else if (/\s/.test(this.get('clusterName'))) {
+ console.log('White spaces not allowed for cluster name');
+ this.set('clusterNameError', Em.I18n.t('installer.step1.clusterName.error.whitespaces'));
+ this.set('invalidClusterName', true);
+ return false;
+ } else if (/[^\w\s]/gi.test(this.get('clusterName'))) {
+ console.log('Special characters are not allowed for the cluster name');
+ this.set('clusterNameError', Em.I18n.t('installer.step1.clusterName.error.specialChar'));
+ this.set('invalidClusterName', true);
+ return false;
+ } else {
+ console.log('value of clusterName is: ' + this.get('clusterName'));
+ this.set('clusterNameError', '');
+ this.set('invalidClusterName', false);
+ db.setClusterName(this.get('clusterName'));
+ return true;
+ }
+ }.observes('clusterName')
+
+})
\ No newline at end of file
Added: incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step2_controller.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step2_controller.js?rev=1386725&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step2_controller.js (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/controllers/installer/step2_controller.js Mon Sep 17 17:17:16 2012
@@ -0,0 +1,258 @@
+/**
+ * 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.InstallerStep2Controller = Em.Controller.extend({
+ name: 'installerStep2Controller',
+ content: [],
+ hostNames: '',
+ hostNameArr: [],
+ hostNameEmptyError: false,
+ hostNameErr: false,
+ manualInstall: false,
+ hostNameNotRequiredErr: false,
+ hostNameErrMsg: '',
+ sshKey: '',
+ passphrase: '',
+ confirmPassphrase: '',
+ sshKeyNullErr: false,
+ passphraseMatchErr: false,
+ localRepo: false,
+ localRepoPath: '',
+ softRepoLocalPathNullErr: false,
+ isSubmitDisabled: false,
+
+ installType: function () {
+ if (this.get('manualInstall') === true) {
+ return 'manualDriven';
+ } else {
+ return 'ambariDriven';
+ }
+ }.observes('manualInstall'),
+
+ hideRepoErrMsg: function () {
+ if (this.get('localRepo') === false) {
+ this.set('softRepoLocalPathNullErr', false);
+ }
+ }.observes('localRepo'),
+
+ validateHostNames: function () {
+ this.hostNameArr = this.get('hostNames').split(new RegExp("\\s"));
+ for (var i = 0; i < this.hostNameArr.length; i++) {
+ //TODO: other validation for hostnames will be covered over here
+ // For now hostnames that start or end with '-' are not allowed
+ if (/^\-/.test(this.hostNameArr[i]) || /\-$/.test(this.hostNameArr[i])) {
+ console.log('Invalid host name: ' + this.hostNameArr[i]);
+ this.set('hostNameErrMsg', Em.I18n.t('installer.step2.hostName.error.invalid'));
+ this.set('hostNameErr', true);
+ this.set('hostNameEmptyError', false);
+ this.set('hostNameNotRequiredErr', false);
+ return false;
+ }
+ }
+ return true;
+ },
+
+ validateHosts: function () {
+ if (this.get('hostNames') === '' && this.get('manualInstall') === false) {
+ this.set('hostNameEmptyError', true);
+ this.set('hostNameNotRequiredErr', false);
+ this.set('hostNameErr', false);
+ this.set('hostNameErrMsg', Em.I18n.t('installer.step2.hostName.error.required'));
+ } else if (this.get('hostNames') !== '' && this.get('manualInstall') === true) {
+ this.set('hostNameNotRequiredErr', true);
+ this.set('hostNameEmptyError', false);
+ this.set('hostNameErr', false);
+ this.set('hostNameErrMsg', Em.I18n.t('installer.step2.hostName.error.notRequired'));
+ } else {
+ this.set('hostNameErr', false);
+ this.set('hostNameEmptyError', false);
+ this.set('hostNameNotRequiredErr', false);
+ this.set('hostNameErrMsg', '');
+ }
+ }.observes('hostNames', 'manualInstall'),
+
+ validateSSHKey: function () {
+ if (this.get('manualInstall') === false) {
+ if (this.get('sshKey') === '') {
+ this.set('sshKeyNullErr', true);
+ }
+ else {
+ this.set('sshKeyNullErr', false);
+ }
+ }
+ }.observes('manualInstall', 'sshKey'),
+
+ validatePassphrase: function () {
+ if (this.get('manualInstall') === false) {
+ if (this.get('passphrase') !== this.get('confirmPassphrase')) {
+ this.set('passphraseMatchErr', true);
+ } else {
+ this.set('passphraseMatchErr', false);
+ }
+ }
+ }.observes('manualInstall', 'passphrase', 'confirmPassphrase'),
+
+ validateLocalRepo: function () {
+ if (this.get('localRepo') === true) {
+ if (this.get('localRepoPath') === '') {
+ this.set('softRepoLocalPathNullErr', true);
+ } else {
+ this.set('softRepoLocalPathNullErr', false);
+ }
+ } else {
+ this.set('softRepoLocalPathNullErr', false);
+ }
+ }.observes('localRepoPath'),
+
+ validateStep2: function () {
+ this.validateHosts();
+ this.validateSSHKey();
+ this.validatePassphrase();
+ this.validateLocalRepo();
+ return this.validateHostNames();
+ },
+
+ hostManageErr: function () {
+ return (this.get('hostNameEmptyError') || this.get('hostNameNotRequiredErr') ||
+ this.get('hostNameErr') || this.get('sshKeyNullErr') || this.get('passphraseMatchErr'));
+ }.property('hostNameErrMsg', 'sshKeyNullErr', 'passphraseMatchErr'),
+
+ sshLessInstall: function () {
+ if (this.get('manualInstall') === true) {
+ this.set('hostManageErr', false);
+ this.set('hostNameEmptyError', false);
+ this.set('sshKeyNullErr', false);
+ this.set('passphraseMatchErr', false);
+ }
+ }.observes('manualInstall'),
+
+ advOptErr: function () {
+ return this.get('softRepoLocalPathNullErr');
+ }.property('softRepoLocalPathNullErr'),
+
+ step2Err: function () {
+ if (this.get('hostManageErr') === true || this.get('advOptErr') === true) {
+ this.set('isSubmitDisabled', true);
+ } else {
+ this.set('isSubmitDisabled', false);
+ }
+ }.observes('hostManageErr', 'advOptErr'),
+
+ softRepo: function () {
+ if (this.get('localRepo') === false) {
+ this.set('localRepoPath', '');
+ }
+ }.observes('localRepo'),
+
+
+ evaluateStep2: function () {
+
+ //task1 = do primary validations on whole step before executing any further steps
+ //task2 = parsing hostnames string to hostnames json array
+ //task3 = check validation for every hostname and store it in localstorage
+ //task4 = Storing ambari agent Install type in localStorage (installType maps at host level and so every host will have this as an property)
+ //task5 = Storing path of software repository(remote/local repo) to localStorage
+ //task6 = call to rest API: @Post http://ambari_server/api/bootstrap
+ //task7 = On Manual Install, next button click pops up a warning with "proceed" and "close" buttons
+ //task8 = On faliure of the previous call, show 'error injecting host information in server db'
+ //task9 = On success of the previous call, go to step 3
+
+ console.log('TRACE: Entering controller:InstallerStep2:evaluateStep2 function');
+ console.log('value of manual install is: ' + this.get('manualInstall'));
+
+ var validateResult = this.validateStep2();
+
+ if (this.get('isSubmitDisabled') === true || validateResult === false) {
+ console.log("ERROR: error in validation");
+ return false;
+ } else {
+ if (this.get('manualInstall') === true) {
+ this.manualInstallPopup();
+ return true;
+ }
+ }
+
+ var hostInfo = {};
+ for (var i = 0; i < this.hostNameArr.length; i++) {
+ hostInfo[this.hostNameArr[i]] = {
+ name: this.hostNameArr[i],
+ installType: this.get('installType')
+ };
+ }
+ App.db.setHosts(hostInfo);
+
+ if (this.get('localRepo') === false) {
+ App.db.setSoftRepo({ 'repoType': 'remote', 'repoPath': null});
+ } else {
+ App.db.setSoftRepo({ 'repoType': 'local', 'repoPath': this.get('localRepoPath') });
+ }
+
+ // Just an additional check. If manualInstall is true, program should have not reached over here
+ if (this.get('manualInstall') === false) {
+ // For now using mock jquery call
+ //TODO: hook up with bootstrap call
+ var bootStrapData = {'sshKey': this.get('sshKey'), 'sshKeyPassphrase': this.get('passphrase'), hosts: this.get('hostNameArr')}.stringify;
+ $.ajax({
+ type: 'POST',
+ url: '/ambari_server/api/bootstrap',
+ data: bootStrapData,
+ async: false,
+ timeout: 2000,
+ success: function () {
+ console.log("TRACE: In success function for the post bootstrap function");
+ App.transitionTo('step3');
+ },
+ error: function () {
+ console.log("ERROR: bootstrap post call failed");
+ return false;
+ },
+ statusCode: {
+ 404: function () {
+ console.log("URI not found.");
+ alert("URI not found,. This needs to be hooked up with a @POST bootstrap call");
+ //After the bootstrap call hook up change the below return statement to "return false"
+ console.log("TRACE: In faliure function for the post bootstrap function");
+ //Remove below line, once bootstrap has been implemented
+ App.router.transitionTo('step3');
+ return true;
+ }
+ },
+ dataType: 'application/json'
+ });
+ } else {
+ console.log("ERROR: ASSERTION FAILED -> program should have never reached over here");
+ }
+
+ },
+
+ manualInstallPopup: function (event) {
+ App.ModalPopup.show({
+ header: Em.I18n.t('installer.step2.manualInstall.popup.header'),
+ onPrimary: function () {
+ this.hide();
+ App.router.transitionTo('step3');
+ },
+ bodyClass: Ember.View.extend({
+ templateName: require('templates/installer/step2ManualInstallPopup')
+ })
+ });
+ }
+
+});
\ No newline at end of file
Modified: incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js?rev=1386725&r1=1386724&r2=1386725&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/app/utils/db.js Mon Sep 17 17:17:16 2012
@@ -18,17 +18,32 @@
var App = require('app');
App.db = {};
-
-Storage.prototype.setObject = function(key,value) {
- this.setItem(key, JSON.stringify(value));
-}
-
-Storage.prototype.getObject = function(key) {
- var value = this.getItem(key);
- return value && JSON.parse(value);
+if (typeof Storage !== 'undefined') {
+ Storage.prototype.setObject = function(key,value) {
+ this.setItem(key, JSON.stringify(value));
+ }
+
+ Storage.prototype.getObject = function(key) {
+ var value = this.getItem(key);
+ return value && JSON.parse(value);
+ }
+} else {
+ // stub for unit testing purposes
+ window.localStorage = {};
+ localStorage.setItem = function (key, val) {
+ this[key] = val;
+ }
+ localStorage.getItem = function (key) {
+ return this[key];
+ }
+ window.localStorage.setObject = function(key, value) {
+ this[key] = value;
+ };
+ window.localStorage.getObject = function(key, value) {
+ return this[key];
+ };
}
-
App.db.cleanUp = function() {
console.log('TRACE: Entering db:cleanup function');
App.db.data = {
@@ -208,3 +223,4 @@ App.db.getHosts = function(name,hostInfo
return App.db.data[user].Installer.hostInfo;
}
+module.exports = App.db;
Modified: incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step1_test.js
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step1_test.js?rev=1386725&r1=1386724&r2=1386725&view=diff
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step1_test.js (original)
+++ incubator/ambari/branches/AMBARI-666/ambari-web/test/installer/step1_test.js Mon Sep 17 17:17:16 2012
@@ -1 +1,37 @@
-// TODO
+var App = require('app');
+require('controllers/installer/step1_controller');
+
+describe('App.InstallerStep1Controller', function () {
+
+ describe('#validateStep1()', function () {
+ it('should return false and sets invalidClusterName to true if cluster name is empty', function () {
+ var controller = App.InstallerStep1Controller.create();
+ controller.set('clusterName', '');
+ expect(controller.validateStep1()).to.equal(false);
+ expect(controller.get('invalidClusterName')).to.equal(true);
+ })
+ it('should return false and sets invalidClusterName to true if cluster name has whitespaces', function () {
+ var controller = App.InstallerStep1Controller.create();
+ controller.set('clusterName', 'My Cluster');
+ expect(controller.validateStep1()).to.equal(false);
+ expect(controller.get('invalidClusterName')).to.equal(true);
+ })
+ it('should return false and sets invalidClusterName to true if cluster name has special characters', function () {
+ var controller = App.InstallerStep1Controller.create();
+ controller.set('clusterName', 'my-cluster');
+ expect(controller.validateStep1()).to.equal(false);
+ expect(controller.get('invalidClusterName')).to.equal(true);
+ })
+ it('should return true, sets invalidClusterName to false, and sets cluster name in db if cluster name is valid', function () {
+ var controller = App.InstallerStep1Controller.create();
+ var clusterName = 'mycluster1';
+ controller.set('clusterName', clusterName);
+ // fake login so clusterName is properly retrieved from App.db
+ App.db.setLoginName('myuser');
+ expect(controller.validateStep1()).to.equal(true);
+ expect(controller.get('invalidClusterName')).to.equal(false);
+ expect(App.db.getClusterName()).to.equal(clusterName);
+ })
+ })
+
+})
\ No newline at end of file