Repository: ambari Updated Branches: refs/heads/trunk d7d0ba288 -> 4c3d38c6f
AMBARI-14371 No eventual config changes should not recommend extra config changes. (ababiichuk) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4c3d38c6 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4c3d38c6 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4c3d38c6 Branch: refs/heads/trunk Commit: 4c3d38c6f989b72a12b0c1461ba0ffca6d66ee76 Parents: d7d0ba2 Author: AndriyBabiychuk <[email protected]> Authored: Fri Dec 18 16:42:35 2015 +0200 Committer: AndriyBabiychuk <[email protected]> Committed: Fri Dec 18 16:42:35 2015 +0200 ---------------------------------------------------------------------- .../mixins/common/configs/enhanced_configs.js | 80 ++++++++++++++------ ambari-web/app/mixins/common/serverValidator.js | 1 + .../models/configs/objects/service_config.js | 15 +++- .../configs/objects/service_config_property.js | 17 +++++ .../app/utils/configs/config_initializer.js | 6 +- .../utils/configs/config_initializer_class.js | 4 +- ambari-web/app/views/common/controls_view.js | 4 +- .../widgets/list_config_widget_view_test.js | 20 ++++- 8 files changed, 113 insertions(+), 34 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/app/mixins/common/configs/enhanced_configs.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/common/configs/enhanced_configs.js b/ambari-web/app/mixins/common/configs/enhanced_configs.js index 678ce87..230493b 100644 --- a/ambari-web/app/mixins/common/configs/enhanced_configs.js +++ b/ambari-web/app/mixins/common/configs/enhanced_configs.js @@ -261,7 +261,6 @@ App.EnhancedConfigsMixin = Em.Mixin.create({ configGroup = this.get('selectedConfigGroup'); } var recommendations = this.get('hostGroups'); - recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(this.get('services'), this.get('stepConfigs')); delete recommendations.config_groups; var dataToSend = { @@ -269,9 +268,15 @@ App.EnhancedConfigsMixin = Em.Mixin.create({ hosts: this.get('hostNames'), services: this.get('serviceNames') }; - if (changedConfigs) { - dataToSend.recommend = 'configuration-dependencies'; - dataToSend.changed_configurations = changedConfigs; + var clearConfigsOnAddService = this.isConfigHasInitialState(); + if (clearConfigsOnAddService) { + recommendations.blueprint.configurations = this.get('initialConfigValues'); + } else { + recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(this.get('services'), this.get('stepConfigs')); + if (changedConfigs) { + dataToSend.recommend = 'configuration-dependencies'; + dataToSend.changed_configurations = changedConfigs; + } } if (!configGroup.get('isDefault') && configGroup.get('hosts.length') > 0) { var configGroups = this.buildConfigGroupJSON(this.get('selectedService.configs'), configGroup); @@ -285,7 +290,8 @@ App.EnhancedConfigsMixin = Em.Mixin.create({ stackVersionUrl: App.get('stackVersionURL'), dataToSend: dataToSend, selectedConfigGroup: configGroup.get('isDefault') ? null : configGroup.get('name'), - initial: initial + initial: initial, + clearConfigsOnAddService: clearConfigsOnAddService }, success: 'dependenciesSuccess', error: 'dependenciesError', @@ -301,6 +307,46 @@ App.EnhancedConfigsMixin = Em.Mixin.create({ }, /** + * Defines if there is any changes made by user. + * Check all properties except recommended properties from popup + * + * @returns {boolean} + */ + isConfigHasInitialState: function() { + return !this.get('stepConfigs').filter(function(stepConfig) { + return stepConfig.get('changedConfigProperties').filter(function(c) { + return !this.get('changedProperties').map(function(changed) { + return App.config.configId(changed.propertyName, changed.fileName); + }).contains(App.config.configId(c.get('name'), c.get('filename'))); + }, this).length; + }, this).length; + }, + + + /** + * Set all config values to their default (initialValue) + */ + clearConfigValues: function() { + this.get('stepConfigs').forEach(function(stepConfig) { + stepConfig.get('changedConfigProperties').forEach(function(c) { + var recommendedProperty = this.get('_dependentConfigValues').find(function(d) { + return App.config.configId(d.propertyName, d.fileName) == App.config.configId(c.get('name'), c.get('filename')); + }); + if (recommendedProperty) { + var initialValue = recommendedProperty.value; + if (Em.isNone(initialValue)) { + stepConfig.get('configs').removeObject(c); + } else { + c.set('value', initialValue); + c.set('recommendedValue', initialValue); + } + this.get('_dependentConfigValues').removeObject(recommendedProperty); + } + }, this) + }, this); + }, + + /** * generates JSON with config group info to send it for recommendations * @param configs * @param configGroup @@ -338,6 +384,10 @@ App.EnhancedConfigsMixin = Em.Mixin.create({ dependenciesSuccess: function (data, opt, params) { this._saveRecommendedValues(data, params.initial, params.dataToSend.changed_configurations, params.selectedConfigGroup); this.set("recommendationsConfigs", Em.get(data.resources[0] , "recommendations.blueprint.configurations")); + if (params.clearConfigsOnAddService) { + this.clearDependenciesForInstalledServices(this.get('installedServiceNames'), this.get('stepConfigs')); + this.clearConfigValues(); + } if (!params.initial) { this.updateDependentConfigs(); } @@ -649,26 +699,6 @@ App.EnhancedConfigsMixin = Em.Mixin.create({ }, /** - * Add and remove dependencies based on recommendations - * - * @param {String[]} [serviceNames=undefined] - list of services to apply changes - */ - addRemoveDependentConfigs: function(serviceNames) { - var self = this; - this.get('stepConfigs').forEach(function(serviceConfigs) { - if (serviceNames && !serviceNames.contains(serviceConfigs.get('serviceName'))) { - return; - } - var selectedGroup = self.getGroupForService(serviceConfigs.get('serviceName')); - if (selectedGroup) { - self._addRecommendedProperties(serviceConfigs, selectedGroup); - self._removeUnRecommendedProperties(serviceConfigs, selectedGroup); - } - }); - }, - - - /** * add configs that was recommended and wasn't present in stepConfigs * @param stepConfigs * @param selectedGroup http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/app/mixins/common/serverValidator.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/common/serverValidator.js b/ambari-web/app/mixins/common/serverValidator.js index b3fb3ad..0306a97 100644 --- a/ambari-web/app/mixins/common/serverValidator.js +++ b/ambari-web/app/mixins/common/serverValidator.js @@ -149,6 +149,7 @@ App.ServerValidatorMixin = Em.Mixin.create({ }) } + this.set('initialConfigValues', recommendations.blueprint.configurations); return App.ajax.send({ 'name': 'config.recommendations', 'sender': this, http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/app/models/configs/objects/service_config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/configs/objects/service_config.js b/ambari-web/app/models/configs/objects/service_config.js index f5da880..2bc151b 100644 --- a/ambari-web/app/models/configs/objects/service_config.js +++ b/ambari-web/app/models/configs/objects/service_config.js @@ -60,7 +60,7 @@ App.ServiceConfig = Ember.Object.extend({ }.observes('configsWithErrors'), observeForeignKeys: function() { - //TODO refactor or move this login to other place + //TODO refactor or move this logic to other place var configs = this.get('configs'); configs.forEach(function (item) { if (item.get('isVisible')) { @@ -103,6 +103,19 @@ App.ServiceConfig = Ember.Object.extend({ return configs.someProperty('isNotDefaultValue'); }, + /** + * Collection of properties that were changed: + * for saved properties use - <code>isNotDefaultValue<code> + * for not saved properties (on wizards, for new services) use + * - <code>isNotInitialValue<code> + * for added properties use - <code>isNotSaved<code> + */ + changedConfigProperties: function() { + return this.get('configs').filter(function(c) { + return c.get('isNotDefaultValue') || c.get('isNotSaved') || c.get('isNotInitialValue'); + }, this); + }.property('[email protected]', '[email protected]', '[email protected]'), + isPropertiesChanged: function() { var requiredByAgent = this.get('configs').filterProperty('isRequiredByAgent'); var isNotSaved = requiredByAgent.someProperty('isNotSaved'); http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/app/models/configs/objects/service_config_property.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/configs/objects/service_config_property.js b/ambari-web/app/models/configs/objects/service_config_property.js index 7a3fbb7..3a4ca3d 100644 --- a/ambari-web/app/models/configs/objects/service_config_property.js +++ b/ambari-web/app/models/configs/objects/service_config_property.js @@ -201,6 +201,23 @@ App.ServiceConfigProperty = Em.Object.extend({ additionalView: null, /** + * If config is saved we should compare config <code>value<code> with <code>savedValue<code> to + * find out if it was changed, but if config in not saved there is no <code>savedValue<code>, so + * we should use <code>initialValue<code> instead. + */ + isNotInitialValue: function() { + if (Em.isNone(this.get('savedValue')) && !Em.isNone(this.get('initialValue'))) { + var value = this.get('value'), initialValue = this.get('initialValue'); + if (this.get('stackConfigProperty.valueAttributes.type') == 'float') { + initialValue = !Em.isNone(initialValue) ? '' + parseFloat(initialValue) : null; + value = '' + parseFloat(value); + } + return initialValue !== value; + } + return false; + }.property('initialValue', 'savedValue', 'value', 'stackConfigProperty.valueAttributes.type'), + + /** * Is property has active override with error */ isValidOverride: function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/app/utils/configs/config_initializer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/config_initializer.js b/ambari-web/app/utils/configs/config_initializer.js index 56ff46e..8c156bb 100644 --- a/ambari-web/app/utils/configs/config_initializer.js +++ b/ambari-web/app/utils/configs/config_initializer.js @@ -573,7 +573,9 @@ App.ConfigInitializer = App.ConfigInitializerClass.create({ var re = new RegExp(regex); recommendedValue = recommendedValue.replace(re, replaceWith); Em.set(configProperty, 'recommendedValue', recommendedValue); - Em.set(configProperty, 'value', Em.isNone(Em.get(configProperty, 'recommendedValue')) ? '' : recommendedValue); + var value = Em.isNone(Em.get(configProperty, 'recommendedValue')) ? '' : recommendedValue; + Em.set(configProperty, 'value', value); + Em.set(configProperty, 'initialValue', value); return configProperty; }, @@ -823,4 +825,4 @@ App.ConfigInitializer = App.ConfigInitializerClass.create({ return allMountPoints; } -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/app/utils/configs/config_initializer_class.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/config_initializer_class.js b/ambari-web/app/utils/configs/config_initializer_class.js index eb29702..3e96fca 100644 --- a/ambari-web/app/utils/configs/config_initializer_class.js +++ b/ambari-web/app/utils/configs/config_initializer_class.js @@ -160,7 +160,7 @@ App.ConfigInitializerClass = Em.Object.extend({ var args = [].slice.call(arguments); return this[uniqueInitializer].apply(this, args); } - + Em.set(configProperty, 'initialValue', Em.get(configProperty, 'value')); return configProperty; }, @@ -295,4 +295,4 @@ App.ConfigInitializerClass = Em.Object.extend({ return source; } -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/app/views/common/controls_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/controls_view.js b/ambari-web/app/views/common/controls_view.js index cef2eb2..2644192 100644 --- a/ambari-web/app/views/common/controls_view.js +++ b/ambari-web/app/views/common/controls_view.js @@ -79,14 +79,14 @@ App.SupportsDependentConfigs = Ember.Mixin.create({ * @returns {$.Deferred} */ sendRequestRorDependentConfigs: function(config) { - if (!config || !config.get('isValid')) return $.Deferred().resolve().promise(); + if (!config || (!config.get('isValid') && config.get('isNotDefaultValue'))) return $.Deferred().resolve().promise(); if (['mainServiceInfoConfigsController','wizardStep7Controller'].contains(this.get('controller.name'))) { var name = config.get('name'); var saveRecommended = (config.get('value') === config.get('recommendedValue')); var controller = this.get('controller'); var type = App.config.getConfigTagFromFileName(config.get('filename')); var p = App.configsCollection.getConfig(App.config.configId(name, type)); - if ((p && Em.get(p, 'propertyDependedBy.length') > 0 || p.displayType === 'user') && config.get('oldValue') !== config.get('value')) { + if ((p && Em.get(p, 'propertyDependedBy.length') > 0 || Em.get(p, 'displayType') === 'user') && config.get('oldValue') !== config.get('value')) { var old = config.get('oldValue'); config.set('oldValue', config.get('value')); return controller.getRecommendationsForDependencies([{ http://git-wip-us.apache.org/repos/asf/ambari/blob/4c3d38c6/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js b/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js index d72e38e..16a24e9 100644 --- a/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js +++ b/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js @@ -129,7 +129,12 @@ describe('App.ListConfigWidgetView', function () { }); describe('#calculateVal', function () { - + beforeEach(function() { + sinon.stub(view, 'sendRequestRorDependentConfigs', Em.K) + }); + afterEach(function() { + view.sendRequestRorDependentConfigs.restore(); + }); it('value updates if some option', function () { view.toggleOption({context: view.get('options')[2]}); expect(view.get('config.value')).to.equal('2,1,3'); @@ -145,11 +150,15 @@ describe('App.ListConfigWidgetView', function () { beforeEach(function() { sinon.stub(view, 'restoreDependentConfigs', Em.K); - sinon.stub(view.get('controller'), 'removeCurrentFromDependentList', Em.K) + sinon.stub(view.get('controller'), 'removeCurrentFromDependentList', Em.K); + sinon.stub(view, 'sendRequestRorDependentConfigs', function() {return { + done: function() {} + }}); }); afterEach(function() { view.restoreDependentConfigs.restore(); view.get('controller.removeCurrentFromDependentList').restore(); + view.sendRequestRorDependentConfigs.restore(); }); it('should restore saved value', function () { view.toggleOption({context: view.get('options')[0]}); @@ -165,6 +174,13 @@ describe('App.ListConfigWidgetView', function () { describe('#toggleOption', function () { + beforeEach(function() { + sinon.stub(view, 'sendRequestRorDependentConfigs', Em.K) + }); + afterEach(function() { + view.sendRequestRorDependentConfigs.restore(); + }); + it('should doesn\'t do nothing if maximum number of options is selected', function () { view.toggleOption({context: view.get('options')[2]}); expect(view.get('options')[2].get('isSelected')).to.be.true;
