Repository: ambari Updated Branches: refs/heads/trunk 2dd2548f3 -> 2557d9a8f
AMBARI-10632. Ranger Admin HA Wizard: Get Started step. (akovalenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2557d9a8 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2557d9a8 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2557d9a8 Branch: refs/heads/trunk Commit: 2557d9a8fb7d9e2f7fe3b2e0deb5b5bec0d14dc1 Parents: 2dd2548 Author: Aleksandr Kovalenko <akovale...@hortonworks.com> Authored: Tue Apr 21 18:44:14 2015 +0300 Committer: Aleksandr Kovalenko <akovale...@hortonworks.com> Committed: Tue Apr 21 19:11:19 2015 +0300 ---------------------------------------------------------------------- .../rangerAdmin/step1_controller.js | 26 ++++++++++- .../rangerAdmin/wizard_controller.js | 2 + ambari-web/app/controllers/wizard.js | 30 +++++++++++-- ambari-web/app/messages.js | 7 +++ .../app/routes/ra_high_availability_routes.js | 9 ++-- .../highAvailability/rangerAdmin/step1.hbs | 21 ++++++++- ambari-web/app/utils/validator.js | 10 +++++ ambari-web/test/controllers/wizard_test.js | 45 ++++++++++++++++++++ ambari-web/test/utils/validator_test.js | 17 ++++++++ 9 files changed, 158 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/step1_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/step1_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/step1_controller.js index d431ec9..32e0dff 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/step1_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/step1_controller.js @@ -17,8 +17,32 @@ */ var App = require('app'); +var validator = require('utils/validator'); App.RAHighAvailabilityWizardStep1Controller = Em.Controller.extend({ - name: "rAHighAvailabilityWizardStep1Controller" + name: "rAHighAvailabilityWizardStep1Controller", + + /** + * Define if typed load balancer URL is valid URL + * @type {Boolean} + */ + isloadBalancerURLValid: function () { + return validator.isValidURL(this.get('content.loadBalancerURL')); + }.property('content.loadBalancerURL'), + + /** + * Define if show load balancer URL error + * do not show is input-field is empty + * @type {Boolean} + */ + showloadBalancerURLError: function () { + return this.get('content.loadBalancerURL') && !this.get('isloadBalancerURLValid'); + }.property('isloadBalancerURLValid', 'content.loadBalancerURL'), + + /** + * Define either Submit is disabled or enabled + * @type {Bolean} + */ + isSubmitDisabled: Ember.computed.not('isloadBalancerURLValid') }); http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/wizard_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/wizard_controller.js b/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/wizard_controller.js index ebfb2ee..5638c87 100644 --- a/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/wizard_controller.js +++ b/ambari-web/app/controllers/main/admin/highAvailability/rangerAdmin/wizard_controller.js @@ -30,6 +30,7 @@ App.RAHighAvailabilityWizardController = App.WizardController.extend({ content: Em.Object.create({ controllerName: 'rAHighAvailabilityWizardController', cluster: null, + loadBalancerURL: null, hosts: null, services: null, masterComponentHosts: null @@ -59,6 +60,7 @@ App.RAHighAvailabilityWizardController = App.WizardController.extend({ type: 'sync', callback: function () { this.load('cluster'); + this.load('loadBalancerURL'); } } ], http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/app/controllers/wizard.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js index d1148a9..5e30777 100644 --- a/ambari-web/app/controllers/wizard.js +++ b/ambari-web/app/controllers/wizard.js @@ -307,6 +307,30 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM }, /** + * Convert any object or array to pure JS instance without inherit properties + * It is used to convert Ember.Object to pure JS Object and Ember.Array to pure JS Array + * @param originalInstance + * @returns {*} + */ + toJSInstance: function (originalInstance) { + var convertedInstance = originalInstance; + if (Em.isArray(originalInstance)) { + convertedInstance = []; + originalInstance.forEach(function (element) { + convertedInstance.push(this.toJSInstance(element)); + }, this) + } else if (originalInstance && typeof originalInstance === 'object') { + convertedInstance = {}; + for (var property in originalInstance) { + if (originalInstance.hasOwnProperty(property)) { + convertedInstance[property] = this.toJSInstance(originalInstance[property]); + } + } + } + return convertedInstance + }, + + /** * save status of the cluster. This is called from step8 and step9 to persist install and start requestId * @param clusterStatus object with status, isCompleted, requestId, isInstallError and isStartError field. */ @@ -485,9 +509,9 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM }, save: function (name) { - var value = this.toObject(this.get('content.' + name)); - this.setDBProperty(name, value); - console.log(this.get('name') + ": saved " + name, value); + var convertedValue = this.toJSInstance(this.get('content.' + name)); + this.setDBProperty(name, convertedValue); + console.log(this.get('name') + ": saved " + name, convertedValue); }, clear: function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 323db48..c5e3740 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -1220,6 +1220,13 @@ Em.I18n.translations = { 'admin.ra_highAvailability.wizard.header': 'Enable Ranger Admin HA Wizard', 'admin.ra_highAvailability.wizard.step1.header': 'Get Started', + 'admin.ra_highAvailability.wizard.step1.body': 'This wizard will walk you through enabling Ranger Admin HA on your cluster.<br/>' + + 'Once enabled, you will be running a Standby Ranger Admin in addition to your Active Ranger Admin.<br/>' + + 'This allows for an Active-Standby Ranger Admin configuration that automatically performs failover.<br/><br/>' + + '<b>You should plan a cluster maintenance window and prepare for cluster downtime when enabling Ranger Admin HA.</b><br/><br/>' + + 'Please setup the load balancer and provide the URL to be used. Make sure that the load balancer is setup properly before proceeding.', + 'admin.ra_highAvailability.wizard.step1.load_balancer_url': 'URL to load balancer', + 'admin.ra_highAvailability.wizard.step1.invalid_url': 'Must be valid URL', 'admin.ra_highAvailability.wizard.step2.header': 'Select Hosts', 'admin.ra_highAvailability.wizard.step2.body': 'Select a host or hosts that will be running the additional Ranger Admin components', 'admin.ra_highAvailability.wizard.step3.header': 'Review', http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/app/routes/ra_high_availability_routes.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/routes/ra_high_availability_routes.js b/ambari-web/app/routes/ra_high_availability_routes.js index 3c076fe..01738f6 100644 --- a/ambari-web/app/routes/ra_high_availability_routes.js +++ b/ambari-web/app/routes/ra_high_availability_routes.js @@ -101,14 +101,15 @@ module.exports = App.WizardRoute.extend({ route: '/step1', connectOutlets: function (router) { var controller = router.get('rAHighAvailabilityWizardController'); - controller.setCurrentStep('1'); controller.dataLoading().done(function () { + controller.setCurrentStep('1'); controller.loadAllPriorSteps().done(function(){ controller.connectOutlet('rAHighAvailabilityWizardStep1', controller.get('content')); }); }) }, next: function (router) { + router.get('rAHighAvailabilityWizardController').save('loadBalancerURL'); router.transitionTo('step2'); } }), @@ -117,8 +118,8 @@ module.exports = App.WizardRoute.extend({ route: '/step2', connectOutlets: function (router) { var controller = router.get('rAHighAvailabilityWizardController'); - controller.setCurrentStep('2'); controller.dataLoading().done(function () { + controller.setCurrentStep('2'); controller.loadAllPriorSteps().done(function(){ controller.connectOutlet('rAHighAvailabilityWizardStep2', controller.get('content')); }); @@ -136,8 +137,8 @@ module.exports = App.WizardRoute.extend({ route: '/step3', connectOutlets: function (router) { var controller = router.get('rAHighAvailabilityWizardController'); - controller.setCurrentStep('3'); controller.dataLoading().done(function () { + controller.setCurrentStep('3'); controller.connectOutlet('rAHighAvailabilityWizardStep3', controller.get('content')); }) }, @@ -153,8 +154,8 @@ module.exports = App.WizardRoute.extend({ route: '/step4', connectOutlets: function (router) { var controller = router.get('rAHighAvailabilityWizardController'); - controller.setCurrentStep('4'); controller.dataLoading().done(function () { + controller.setCurrentStep('4'); controller.connectOutlet('rAHighAvailabilityWizardStep4', controller.get('content')); }) }, http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/app/templates/main/admin/highAvailability/rangerAdmin/step1.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/main/admin/highAvailability/rangerAdmin/step1.hbs b/ambari-web/app/templates/main/admin/highAvailability/rangerAdmin/step1.hbs index bb7745d..b92d1c6 100644 --- a/ambari-web/app/templates/main/admin/highAvailability/rangerAdmin/step1.hbs +++ b/ambari-web/app/templates/main/admin/highAvailability/rangerAdmin/step1.hbs @@ -16,6 +16,25 @@ right ownership. The ASF licenses this file * See the License for the specific language governing permissions and * limitations under the License. }} +<div> + <h2>{{t admin.ra_highAvailability.wizard.step1.header}}</h2> + + <div class="alert alert-info"> + {{t admin.ra_highAvailability.wizard.step1.body}} + </div> + <form class="form-horizontal"> + <div {{bindAttr class=":control-group showloadBalancerURLError:error"}}> + <label class="control-label">{{t admin.ra_highAvailability.wizard.step1.load_balancer_url}}:</label> + + <div class="controls"> + {{view Em.TextField valueBinding="content.loadBalancerURL"}} + {{#if showloadBalancerURLError}} + <span class="help-inline">{{t admin.ra_highAvailability.wizard.step1.invalid_url}}</span> + {{/if}} + </div> + </div> + </form> +</div> <div class="btn-area"> - <a class="btn btn-success pull-right" {{action next}}>{{t common.next}} →</a> + <button class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action next}}>{{t common.next}} →</button> </div> http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/app/utils/validator.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/validator.js b/ambari-web/app/utils/validator.js index fe7e286..00b02d9 100644 --- a/ambari-web/app/utils/validator.js +++ b/ambari-web/app/utils/validator.js @@ -223,5 +223,15 @@ module.exports = { isValidRackId: function(path) { // See app/message.js:hostPopup.setRackId.invalid return /^\/[/.\w-]+$/.test(path); + }, + + /** + * Validate url + * @param value + * @return {Boolean} + */ + isValidURL: function(value) { + var urlRegex = /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7 FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i; + return urlRegex.test(value); } }; http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/test/controllers/wizard_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/wizard_test.js b/ambari-web/test/controllers/wizard_test.js index 79bfc5a..9b9c06f 100644 --- a/ambari-web/test/controllers/wizard_test.js +++ b/ambari-web/test/controllers/wizard_test.js @@ -308,4 +308,49 @@ describe('App.WizardController', function () { }); }); + + describe('#toJSInstance', function () { + + var testCases = [ + { + o: {'test': 'test'}, + e: {'test': 'test'} + }, + { + o: {'test': Em.Object.create()}, + e: {'test': {}} + }, + { + o: {'test': Em.Object.create({'test': {}})}, + e: {'test': {'test': {}}} + }, + { + o: [], + e: [] + }, + { + o: Em.A([[]]), + e: [[]] + }, + { + o: 11, + e: 11 + }, + { + o: '11', + e: '11' + }, + { + o: null, + e: null + } + ]; + + it('should convert objects and arrays to pure JS objects and arrays', function () { + testCases.forEach(function (testCase) { + expect(c.toJSInstance(testCase.o)).to.eql(testCase.e); + }); + }); + + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/2557d9a8/ambari-web/test/utils/validator_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/utils/validator_test.js b/ambari-web/test/utils/validator_test.js index bccb820..1ad5989 100644 --- a/ambari-web/test/utils/validator_test.js +++ b/ambari-web/test/utils/validator_test.js @@ -407,4 +407,21 @@ describe('validator', function () { }) }); }); + + describe('#isValidURL', function() { + var tests = [ + {m:'"http://apache.org" - valid',i:'http://apache.org',e:true}, + {m:'"http://ambari.apache.org" - valid',i:'http://ambari.apache.org',e:true}, + {m:'"https://ambari.apache.org" - valid',i:'https://ambari.apache.org',e:true}, + {m:'"htp://ambari.apache.org." - invalid',i:'.htp://ambari.apache.org.',e:false}, + {m:'"ambari.apache.org" - invalid',i:'ambari.apache.org',e:false}, + {m:'"www.ambari.apache.org" - invalid',i:'www.ambari.apache.org',e:false}, + {m:'"" - invalid',i:'',e:false} + ]; + tests.forEach(function(test) { + it(test.m + ' ', function () { + expect(validator.isValidURL(test.i)).to.equal(test.e); + }) + }); + }); });