Browse Source

AMBARI-14371 No eventual config changes should not recommend extra config changes. (ababiichuk)

AndriyBabiychuk 9 years ago
parent
commit
4c3d38c6f9

+ 55 - 25
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',
@@ -300,6 +306,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
@@ -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();
     }
@@ -648,26 +698,6 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
     this.set('recommendationTimeStamp', (new Date).getTime());
   },
 
-  /**
-   * 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

+ 1 - 0
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,

+ 14 - 1
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('configs.@each.isNotDefaultValue', 'configs.@each.isNotSaved', 'configs.@each.isNotInitialValue'),
+
   isPropertiesChanged: function() {
     var requiredByAgent = this.get('configs').filterProperty('isRequiredByAgent');
     var isNotSaved = requiredByAgent.someProperty('isNotSaved');

+ 17 - 0
ambari-web/app/models/configs/objects/service_config_property.js

@@ -200,6 +200,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
    */

+ 4 - 2
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;
   }
 
-});
+});

+ 2 - 2
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;
   }
 
-});
+});

+ 2 - 2
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([{

+ 18 - 2
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;