Repository: ambari Updated Branches: refs/heads/branch-2.1 33c694b18 -> 0731e999d
AMBARI-12911. FE: Stack Meta for JDK support (alexantonenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/0731e999 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/0731e999 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/0731e999 Branch: refs/heads/branch-2.1 Commit: 0731e999d98a014201b25b1f3a112977ea18e886 Parents: 33c694b Author: Alex Antonenko <[email protected]> Authored: Fri Aug 28 13:06:10 2015 +0300 Committer: Alex Antonenko <[email protected]> Committed: Fri Aug 28 13:46:58 2015 +0300 ---------------------------------------------------------------------- .../controllers/global/cluster_controller.js | 8 ++ ambari-web/app/controllers/installer.js | 53 ++++++++++- ambari-web/app/mappers/stack_mapper.js | 4 +- ambari-web/app/messages.js | 4 + ambari-web/app/models/stack.js | 2 + ambari-web/app/routes/installer.js | 14 +-- ambari-web/app/utils/string_utils.js | 6 +- ambari-web/test/controllers/installer_test.js | 95 +++++++++++++++++++- 8 files changed, 175 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/app/controllers/global/cluster_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js index e182719..f564daa 100644 --- a/ambari-web/app/controllers/global/cluster_controller.js +++ b/ambari-web/app/controllers/global/cluster_controller.js @@ -41,6 +41,12 @@ App.ClusterController = Em.Controller.extend({ isServiceMetricsLoaded: false, + /** + * Ambari uses custom jdk. + * @type {Boolean} + */ + isCustomJDK: false, + isHostContentLoaded: function () { return this.get('isHostsLoaded') && this.get('isComponentsStateLoaded'); }.property('isHostsLoaded', 'isComponentsStateLoaded'), @@ -349,6 +355,8 @@ App.ClusterController = Em.Controller.extend({ loadAmbariPropertiesSuccess: function (data) { console.log('loading ambari properties'); this.set('ambariProperties', data.RootServiceComponents.properties); + // Absence of 'jdk.name' and 'jce.name' properties says that ambari configured with custom jdk. + this.set('isCustomJDK', App.isEmptyObject(App.permit(data.RootServiceComponents.properties, ['jdk.name', 'jce.name']))); }, loadAmbariPropertiesError: function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/app/controllers/installer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js index 3e97c4f..82e13f4 100644 --- a/ambari-web/app/controllers/installer.js +++ b/ambari-web/app/controllers/installer.js @@ -18,6 +18,7 @@ var App = require('app'); +var stringUtils = require('utils/string_utils'); App.InstallerController = App.WizardController.extend({ @@ -606,7 +607,15 @@ App.InstallerController = App.WizardController.extend({ { type: 'async', callback: function () { - return this.loadStacks(); + var dfd = $.Deferred(); + + this.loadStacks().always(function() { + App.router.get('clusterController').loadAmbariProperties().always(function() { + dfd.resolve(); + }); + }); + + return dfd.promise(); } }, { @@ -719,5 +728,47 @@ App.InstallerController = App.WizardController.extend({ var step = this.get('isStepDisabled').findProperty('step', i); step.set('value', true); } + }, + + + /** + * Compare jdk versions used for ambari and selected stack. + * Validation check will fire only for non-custom jdk configuration. + * + * @param {Function} successCallback + * @param {Function} failCallback + */ + validateJDKVersion: function (successCallback, failCallback) { + var selectedStack = App.Stack.find().findProperty('isSelected', true), + currentJDKVersion = App.router.get('clusterController.ambariProperties')['java.version'], + minJDKVersion = selectedStack.get('minJdkVersion'), + maxJDKVersion = selectedStack.get('maxJdkVersion'), + t = Em.I18n.t, + fCallback = failCallback || function() {}, + sCallback = successCallback || function() {}; + + // Skip jdk check if min and max required version not set in stack definition. + if (!minJDKVersion && !maxJDKVersion) { + sCallback(); + return; + } + + if (currentJDKVersion) { + if (stringUtils.compareVersions(currentJDKVersion, selectedStack.get('minJdkVersion')) < 0 || + stringUtils.compareVersions(selectedStack.get('maxJdkVersion'), currentJDKVersion) < 0) { + // checks and process only major part for now + var versionDistance = parseInt(maxJDKVersion.split('.')[1]) - parseInt(minJDKVersion.split('.')[1]); + var versionsList = [minJDKVersion]; + for (var i = 1; i < (versionDistance + 1); i++) { + versionsList.push("" + minJDKVersion.split('.')[0] + '.' + (+minJDKVersion.split('.')[1] + i)); + } + var versionsString = stringUtils.getFormattedStringFromArray(versionsList, t('or')); + var popupBody = t('popup.jdkValidation.body').format(selectedStack.get('stackName') + ' ' + selectedStack.get('stackVersion'), versionsString, currentJDKVersion); + App.showConfirmationPopup(sCallback, popupBody, fCallback, t('popup.jdkValidation.header'), t('common.proceedAnyway'), true); + return; + } + } + sCallback(); } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/app/mappers/stack_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/stack_mapper.js b/ambari-web/app/mappers/stack_mapper.js index eb64ef6..75245e0 100644 --- a/ambari-web/app/mappers/stack_mapper.js +++ b/ambari-web/app/mappers/stack_mapper.js @@ -29,6 +29,8 @@ App.stackMapper = App.QuickDataMapper.create({ active: 'active', parent_stack_version: 'parent_stack_version', min_upgrade_version: 'min_upgrade_version', + min_jdk_version: 'min_jdk', + max_jdk_version: 'max_jdk', is_selected: 'is_selected', config_types: 'config_types', operating_systems_key: 'operating_systems', @@ -111,4 +113,4 @@ App.stackMapper = App.QuickDataMapper.create({ App.store.loadMany(modelOS, resultOS); App.store.loadMany(modelStack, resultStack); } -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index c0852d4..9fdc28c 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -63,6 +63,7 @@ Em.I18n.translations = { 'add': 'Add', 'op': 'op', 'ops': 'ops', + 'or': 'or', 'common.access':'Access', @@ -382,6 +383,9 @@ Em.I18n.translations = { 'popup.dependent.configs.dependencies.for.groups': 'You are changing not default group, please select config group to which you want to save dependent configs from other services', + 'popup.jdkValidation.header': 'Unsupported JDK', + 'popup.jdkValidation.body': 'The {0} Stack requires JDK {1} but Ambari is configured for JDK {2}. This could result in error or problems with running your cluster.', + 'login.header':'Sign in', 'login.username':'Username', 'login.loginButton':'Sign in', http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/app/models/stack.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/stack.js b/ambari-web/app/models/stack.js index e6cd0d8..0b1c9d2 100644 --- a/ambari-web/app/models/stack.js +++ b/ambari-web/app/models/stack.js @@ -25,6 +25,8 @@ App.Stack = DS.Model.extend({ active: DS.attr('boolean'), // All of the instances should have this value to true. We should map only those stacks that has active flag set to true parentStackVersion: DS.attr('string'), minUpgradeVersion: DS.attr('string'), + minJdkVersion: DS.attr('string'), + maxJdkVersion: DS.attr('string'), configTypes: DS.attr('object'), operatingSystems: DS.hasMany('App.OperatingSystem'), isSelected: DS.attr('boolean', {defaultValue: false}), http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/app/routes/installer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/routes/installer.js b/ambari-web/app/routes/installer.js index c5d1a64..90ca2f2 100644 --- a/ambari-web/app/routes/installer.js +++ b/ambari-web/app/routes/installer.js @@ -128,12 +128,14 @@ module.exports = Em.Route.extend(App.RouterRedirections, { next: function (router) { var wizardStep1Controller = router.get('wizardStep1Controller'); var installerController = router.get('installerController'); - installerController.checkRepoURL(wizardStep1Controller).done(function () { - installerController.setDBProperty('service', undefined); - installerController.setStacks(); - installerController.clearInstallOptions(); - router.transitionTo('step2'); - }); + installerController.validateJDKVersion(function() { + installerController.checkRepoURL(wizardStep1Controller).done(function () { + installerController.setDBProperty('service', undefined); + installerController.setStacks(); + installerController.clearInstallOptions(); + router.transitionTo('step2'); + }); + }, function() {}); } }), http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/app/utils/string_utils.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/string_utils.js b/ambari-web/app/utils/string_utils.js index 48f8e52..3b14bfc 100644 --- a/ambari-web/app/utils/string_utils.js +++ b/ambari-web/app/utils/string_utils.js @@ -167,10 +167,12 @@ module.exports = { * var arr = [ambari, bigdata, hadoop] * getFormattedStringFromArray(arr); // ambari, bigdata and hadoop * @param array {Array} Array of elements + * @param [endSeparator=Em.I18n.t('and')] {String} * @returns {String} */ - getFormattedStringFromArray: function (array) { + getFormattedStringFromArray: function (array, endSeparator) { var label = ''; + endSeparator = endSeparator || Em.I18n.t('and'); array.forEach(function (_arrElement) { if (array.length === 1) { label = _arrElement; @@ -183,7 +185,7 @@ module.exports = { } } else { - label = label + ' ' + Em.I18n.t('and') + ' ' + _arrElement; + label = label + ' ' + endSeparator + ' ' + _arrElement; } } }, this); http://git-wip-us.apache.org/repos/asf/ambari/blob/0731e999/ambari-web/test/controllers/installer_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/installer_test.js b/ambari-web/test/controllers/installer_test.js index df5c8f4..23c00a7 100644 --- a/ambari-web/test/controllers/installer_test.js +++ b/ambari-web/test/controllers/installer_test.js @@ -469,7 +469,11 @@ describe('App.InstallerController', function () { var loadStacks = false; var checker = { loadStacks: function() { - loadStacks = true; + return { + always: function() { + loadStacks = true; + } + }; } }; installerController.loadMap['1'][0].callback.call(checker); @@ -967,4 +971,93 @@ describe('App.InstallerController', function () { }); + describe('#validateJDKVersion', function() { + var tests = [ + { + isCustomJDK: false, + ambariProperties: { + 'java.version': '1.8' + }, + successCallbackCalled: false, + popupCalled: true, + stacks: [Em.Object.create({ + minJdkVersion: '1.6', + maxJdkVersion: '1.7', + isSelected: true + })], + m: 'JDK 1.8, stack supports 1.6-1.7 popup should be displayed' + }, + { + isCustomJDK: false, + ambariProperties: { + 'java.version': '1.8' + }, + successCallbackCalled: true, + popupCalled: false, + stacks: [Em.Object.create({ + minJdkVersion: '1.6', + maxJdkVersion: '1.8', + isSelected: true + })], + m: 'JDK 1.8, stack supports 1.7-1.8 procceed installation without warning' + }, + { + isCustomJDK: false, + ambariProperties: { + 'java.version': '1.5' + }, + successCallbackCalled: false, + popupCalled: true, + stacks: [Em.Object.create({ + minJdkVersion: '1.6', + maxJdkVersion: '1.8', + isSelected: true + })], + m: 'JDK 1.5, stack supports 1.6-1.8, popup should be displayed' + }, + { + isCustomJDK: false, + ambariProperties: { + 'java.version': '1.8' + }, + successCallbackCalled: true, + popupCalled: false, + stacks: [Em.Object.create({ + isSelected: true + })], + m: 'JDK 1.8, min, max jdk missed in stack definition, procceed installation without warning' + }, + { + isCustomJDK: true, + ambariProperties: { + 'java.version': '1.8' + }, + successCallbackCalled: true, + popupCalled: false, + stacks: [Em.Object.create({ + minJdkVersion: '1.6', + maxJdkVersion: '1.8', + isSelected: true + })], + m: 'JDK 1.8, custom jdk location used, procceed installation without warning' + } + ]; + + tests.forEach(function(test) { + it(test.m, function() { + sinon.stub(App.Stack, 'find').returns(test.stacks); + sinon.stub(App.router, 'get').withArgs('clusterController.isCustomJDK').returns(test.isCustomJDK) + .withArgs('clusterController.ambariProperties').returns(test.ambariProperties); + sinon.stub(App, 'showConfirmationPopup', Em.K); + var successCallback = sinon.spy(); + installerController.validateJDKVersion(successCallback); + expect(successCallback.called).to.be.eql(test.successCallbackCalled); + expect(App.showConfirmationPopup.called).to.be.eql(test.popupCalled); + App.router.get.restore(); + App.Stack.find.restore(); + App.showConfirmationPopup.restore(); + }); + }); + }); + });
