AMBARI-14501 Improve config recommendations flow 2. (ababiichuk)

Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/73a850eb
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/73a850eb
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/73a850eb

Branch: refs/heads/branch-dev-patch-upgrade
Commit: 73a850eb0bb781d3f6650b176d375aca9b5021f2
Parents: ff3643c
Author: ababiichuk <[email protected]>
Authored: Mon Dec 28 13:01:20 2015 +0200
Committer: ababiichuk <[email protected]>
Committed: Mon Dec 28 14:17:03 2015 +0200

----------------------------------------------------------------------
 .../controllers/main/service/info/configs.js    |  16 +-
 .../app/controllers/wizard/step7_controller.js  |  86 +++-
 ambari-web/app/mixins.js                        |   3 +
 .../configs/config_recommendation_parser.js     | 248 ++++++++++
 .../common/configs/config_recommendations.js    | 201 ++++++++
 ...onfig_with_override_recommendation_parser.js | 113 +++++
 .../app/mixins/common/configs/configs_saver.js  |   2 +-
 .../mixins/common/configs/enhanced_configs.js   | 464 ++-----------------
 ambari-web/app/mixins/common/serverValidator.js |   2 +-
 .../models/configs/objects/service_config.js    |   4 +
 .../configs/objects/service_config_property.js  |  14 +
 ambari-web/app/routes/add_service_routes.js     |   2 +-
 .../modal_popups/dependent_configs_list.hbs     |   4 +-
 ambari-web/app/utils/config.js                  |  26 +-
 ambari-web/app/views/common/controls_view.js    |   4 +-
 .../common/modal_popups/select_groups_popup.js  |   2 +-
 .../main/service/info/config_test.js            |   4 +-
 .../common/configs/enhanced_configs_test.js     |  10 +-
 .../configs/widgets/config_widget_view_test.js  |  14 +-
 19 files changed, 770 insertions(+), 449 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js 
b/ambari-web/app/controllers/main/service/info/configs.js
index 1eef9a1..85b4f60 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -264,7 +264,7 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ConfigsLoader, A
     this.get('requestsInProgress').clear();
     this.clearLoadInfo();
     this.clearSaveInfo();
-    this.clearDependentConfigs();
+    this.clearAllRecommendations();
     this.setProperties({
       saveInProgress: false,
       isInit: true,
@@ -536,6 +536,18 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ConfigsLoader, A
   },
 
   /**
+   * Allow update property if recommendations
+   * is based on changing property
+   *
+   * @param parentProperties
+   * @returns {boolean}
+   * @override
+   */
+  allowUpdateProperty: function(parentProperties) {
+    return !!(parentProperties && parentProperties.length);
+  },
+
+  /**
    * trigger App.config.createOverride
    * @param {Object[]} stepConfig
    * @private
@@ -576,7 +588,7 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ConfigsLoader, A
    */
   doCancel: function () {
     this.set('preSelectedConfigVersion', null);
-    this.clearDependentConfigs();
+    this.clearAllRecommendations();
     this.loadSelectedVersion(this.get('selectedVersion'), 
this.get('selectedConfigGroup'));
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/controllers/wizard/step7_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step7_controller.js 
b/ambari-web/app/controllers/wizard/step7_controller.js
index 2726236..823d663 100644
--- a/ambari-web/app/controllers/wizard/step7_controller.js
+++ b/ambari-web/app/controllers/wizard/step7_controller.js
@@ -706,18 +706,11 @@ App.WizardStep7Controller = 
Em.Controller.extend(App.ServerValidatorMixin, App.E
     if (rangerService && !rangerService.get('isInstalled') && 
!rangerService.get('isSelected')) {
       App.config.removeRangerConfigs(self.get('stepConfigs'));
     }
-    this.loadServerSideConfigsRecommendations().always(function() {
-      if (self.get('wizardController.name') == 'addServiceController') {
-        // for Add Service just remove or add dependent properties and ignore 
config values changes
-        // for installed services only
-        
self.clearDependenciesForInstalledServices(self.get('installedServiceNames'), 
self.get('stepConfigs'));
-      }
-      self.completeConfigLoading();
-    });
+    
this.loadServerSideConfigsRecommendations().always(this.completeConfigLoading.bind(this));
   },
 
   completeConfigLoading: function() {
-    
this.clearDependentConfigsByService(App.StackService.find().filterProperty('isSelected').mapProperty('serviceName'));
+    
this.clearRecommendationsByServiceName(App.StackService.find().filterProperty('isSelected').mapProperty('serviceName'));
     console.timeEnd('wizard loadStep: ');
     this.set('isRecommendedLoaded', true);
     if (this.get('content.skipConfigStep')) {
@@ -727,6 +720,17 @@ App.WizardStep7Controller = 
Em.Controller.extend(App.ServerValidatorMixin, App.E
   },
 
   /**
+   * Update initialValues only while loading recommendations first time
+   *
+   * @param serviceName
+   * @returns {boolean}
+   * @override
+   */
+  updateInitialOnRecommendations: function(serviceName) {
+    return this._super(serviceName) && !this.get('isRecommendedLoaded');
+  },
+
+  /**
    * Mark descriptor properties in configuration object.
    *
    * @param {Object[]} configs - config properties to change
@@ -1224,6 +1228,70 @@ App.WizardStep7Controller = 
Em.Controller.extend(App.ServerValidatorMixin, App.E
   },
 
   /**
+   * @param serviceName
+   * @returns {boolean}
+   * @override
+   */
+  useInitialValue: function(serviceName) {
+    return !App.Service.find(serviceName).get('serviceName', serviceName);
+  },
+
+  /**
+   *
+   * @param parentProperties
+   * @param name
+   * @param fileName
+   * @returns {*}
+   * @override
+   */
+  allowUpdateProperty: function(parentProperties, name, fileName) {
+    if (['installerController'].contains(this.get('wizardController.name')) || 
!!(parentProperties && parentProperties.length)) {
+      return true;
+    } else if 
(['addServiceController'].contains(this.get('wizardController.name'))) {
+      var stackProperty = App.configsCollection.getConfigByName(name, 
fileName);
+      if (!stackProperty || 
!this.get('installedServices')[stackProperty.serviceName]) {
+        return true;
+      } else if (stackProperty.propertyDependsOn.length) {
+        return stackProperty.propertyDependsOn.filter(function (p) {
+          var service = App.config.getServiceByConfigType(p.type);
+          return service && 
!this.get('installedServices')[service.get('serviceName')];
+        }, this).length;
+      } else {
+        return false;
+      }
+    }
+    return true;
+  },
+
+  /**
+   * remove config based on recommendations
+   * @param config
+   * @param configsCollection
+   * @param parentProperties
+   * @protected
+   * @override
+   */
+  _removeConfigByRecommendation: function (config, configsCollection, 
parentProperties) {
+    this._super(config, configsCollection, parentProperties);
+    /**
+     * need to update wizard info when removing configs for installed services;
+     */
+    var installedServices = this.get('installedServices'), wizardController = 
this.get('wizardController'),
+      fileNamesToUpdate = wizardController ? 
wizardController.getDBProperty('fileNamesToUpdate') || [] : [],
+      fileName = Em.get(config, 'filename'), serviceName = Em.get(config, 
'serviceName');
+    var modifiedFileNames = this.get('modifiedFileNames');
+    if (modifiedFileNames && !modifiedFileNames.contains(fileName)) {
+      modifiedFileNames.push(fileName);
+    } else if (wizardController && installedServices[serviceName]) {
+      if (!fileNamesToUpdate.contains(fileName)) {
+        fileNamesToUpdate.push(fileName);
+      }
+    }
+    if (wizardController) {
+      wizardController.setDBProperty('fileNamesToUpdate', 
fileNamesToUpdate.uniq());
+    }
+  },
+  /**
    * @method manageConfigurationGroup
    */
   manageConfigurationGroup: function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/mixins.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins.js b/ambari-web/app/mixins.js
index 90fbaa2..38d112d 100644
--- a/ambari-web/app/mixins.js
+++ b/ambari-web/app/mixins.js
@@ -45,6 +45,9 @@ require('mixins/wizard/selectHost');
 require('mixins/wizard/addSecurityConfigs');
 require('mixins/wizard/wizard_menu_view');
 require('mixins/wizard/assign_master_components');
+require('mixins/common/configs/config_recommendations');
+require('mixins/common/configs/config_recommendation_parser');
+require('mixins/common/configs/config_with_override_recommendation_parser');
 require('mixins/common/configs/enhanced_configs');
 require('mixins/common/configs/configs_saver');
 require('mixins/common/configs/configs_loader');

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/mixins/common/configs/config_recommendation_parser.js
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/mixins/common/configs/config_recommendation_parser.js 
b/ambari-web/app/mixins/common/configs/config_recommendation_parser.js
new file mode 100644
index 0000000..4da42dd
--- /dev/null
+++ b/ambari-web/app/mixins/common/configs/config_recommendation_parser.js
@@ -0,0 +1,248 @@
+/**
+ * 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 validator = require('utils/validator');
+
+App.ConfigRecommendationParser = Em.Mixin.create(App.ConfigRecommendations, {
+
+       stepConfigs: [],
+
+       /**
+        * Method that goes through all configs
+        * and apply recommendations using callbacks
+        *
+        * @param recommendationObject
+        * @param configs
+        * @param parentProperties
+        * @param configGroup
+        * @param updateCallback
+        * @param removeCallback
+        * @param updateBoundariesCallback
+        */
+       parseRecommendations: function(recommendationObject, configs, 
parentProperties, configGroup,
+                                      updateCallback, removeCallback, 
updateBoundariesCallback) {
+               var propertiesToDelete = [];
+               configs.forEach(function (config) {
+                       var name = Em.get(config, 'name'), fileName = 
Em.get(config, 'filename'),
+                               site = 
App.config.getConfigTagFromFileName(fileName);
+                       if (recommendationObject[site]) {
+                               var properties = 
recommendationObject[site].properties,
+                                       property_attributes = 
recommendationObject[site].property_attributes;
+                               if (properties) {
+                                       var recommendedValue = 
App.config.formatValue(properties[name]);
+                                       if (!Em.isNone(recommendedValue)) {
+                                               /** update config **/
+                                               updateCallback(config, 
recommendedValue, parentProperties, configGroup);
+
+                                               delete 
recommendationObject[site].properties[name];
+                                       }
+                               }
+                               if (property_attributes) {
+                                       var propertyAttributes = 
property_attributes[name];
+                                       var stackProperty = 
App.configsCollection.getConfigByName(name, fileName);
+                                       for (var attr in propertyAttributes) {
+                                               if (attr == 'delete' && 
this.allowUpdateProperty(parentProperties, name, fileName)) {
+                                                       
propertiesToDelete.push(config);
+                                               } else if (stackProperty) {
+                                                       /** update config 
boundaries **/
+                                                       
updateBoundariesCallback(stackProperty, attr, propertyAttributes[attr], 
configGroup);
+                                               }
+                                       }
+                               }
+                       }
+               }, this);
+
+               if (propertiesToDelete.length) {
+                       propertiesToDelete.forEach(function (property) {
+                               /** remove config **/
+                               removeCallback(property, configs, 
parentProperties, configGroup);
+
+                       }, this);
+               }
+       },
+
+       /**
+        * Method that goes through all configs
+        * and apply recommendations to configs when it's needed
+        *
+        * @param {Object} recommendationObject
+        * @param {Object[]} configs
+        * @param {Object[]} parentProperties
+        */
+       updateConfigsByRecommendations: function (recommendationObject, 
configs, parentProperties) {
+               this.parseRecommendations(recommendationObject, configs, 
parentProperties, null,
+                       this._updateConfigByRecommendation.bind(this), 
this._removeConfigByRecommendation.bind(this), 
this._updateBoundaries.bind(this));
+       },
+
+       /**
+        * This method goes through all config recommendations
+        * and trying to add new properties
+        *
+        * @param {Object} recommendationObject
+        * @param {Object[]} parentProperties
+        */
+       addByRecommendations: function (recommendationObject, parentProperties) 
{
+               for (var site in recommendationObject) {
+                       if 
(Object.keys(recommendationObject[site].properties).length) {
+                               var stepConfig = 
App.config.getStepConfigForProperty(this.get('stepConfigs'), site), configs = 
[];
+                               if (stepConfig) {
+                                       for (var propertyName in 
recommendationObject[site].properties) {
+                                               if 
(this.allowUpdateProperty(parentProperties, propertyName, site)) {
+                                                       
this._addConfigByRecommendation(configs, propertyName, site, 
recommendationObject[site].properties[propertyName], parentProperties);
+                                               }
+                                       }
+                                       var mergedConfigs = 
configs.concat(stepConfig.get('configs'));
+                                       stepConfig.set('configs', 
mergedConfigs);
+                               }
+                       }
+               }
+       },
+
+       /**
+        * Update config based on recommendations
+        *
+        * @param config
+        * @param recommendedValue
+        * @param parentProperties
+        * @protected
+        */
+       _updateConfigByRecommendation: function (config, recommendedValue, 
parentProperties) {
+               Em.assert('config should be defined', config);
+               Em.set(config, 'recommendedValue', recommendedValue);
+               if (this.allowUpdateProperty(parentProperties, Em.get(config, 
'name'), Em.get(config, 'filename'))) {
+                       Em.set(config, 'value', recommendedValue);
+                       this.applyRecommendation(Em.get(config, 'name'), 
Em.get(config, 'filename'), Em.get(config, 'group.name'), recommendedValue, 
this._getInitialValue(config), parentProperties);
+               }
+               if (this.updateInitialOnRecommendations(Em.get(config, 
'serviceName'))) {
+                       Em.set(config, 'initialValue', recommendedValue);
+               }
+       },
+
+       /**
+        * Add config based on recommendations
+        *
+        * @param configs
+        * @param name
+        * @param fileName
+        * @param recommendedValue
+        * @param parentProperties
+        * @protected
+        */
+       _addConfigByRecommendation: function (configs, name, fileName, 
recommendedValue, parentProperties) {
+               fileName = App.config.getOriginalFileName(fileName);
+               var stackConfig = App.configsCollection.getConfigByName(name, 
fileName),
+                       service = 
App.config.get('serviceByConfigTypeMap')[App.config.getConfigTagFromFileName(fileName)];
+               if (service) {
+                       var serviceName = stackConfig ? stackConfig.serviceName 
: service && service.get('serviceName'),
+                               popupProperty = this.getRecommendation(name, 
fileName),
+                               initialValue = popupProperty ? 
popupProperty.value : null;
+
+                       var coreObject = {
+                               "value": recommendedValue,
+                               "recommendedValue": recommendedValue,
+                               "initialValue": 
this.updateInitialOnRecommendations(serviceName) ? recommendedValue : 
initialValue,
+                               "savedValue": 
!this.useInitialValue(serviceName) && !Em.isNone(initialValue) ? initialValue : 
null
+                       };
+                       var addedProperty = stackConfig || 
App.config.createDefaultConfig(name, serviceName, fileName, false);
+                       Em.setProperties(addedProperty, coreObject);
+                       var addedPropertyObject = 
App.ServiceConfigProperty.create(addedProperty);
+                       configs.pushObject(addedPropertyObject);
+                       addedPropertyObject.validate();
+
+                       this.applyRecommendation(name, fileName, "Default",
+                               recommendedValue, null, parentProperties);
+               }
+       },
+
+       /**
+        * Remove config based on recommendations
+        *
+        * @param config
+        * @param configsCollection
+        * @param parentProperties
+        * @protected
+        */
+       _removeConfigByRecommendation: function (config, configsCollection, 
parentProperties) {
+               Em.assert('config and configsCollection should be defined', 
config && configsCollection);
+               configsCollection.removeObject(config);
+
+               this.applyRecommendation(Em.get(config, 'name'), Em.get(config, 
'filename'), Em.get(config, 'group.name'),
+                       null, this._getInitialValue(config), parentProperties);
+       },
+
+       /**
+        * Update config valueAttributes by recommendations
+        *
+        * @param {Object} stackProperty
+        * @param {string} attr
+        * @param {Number|String|Boolean} value
+        * @protected
+        */
+       _updateBoundaries: function(stackProperty, attr, value) {
+               Em.set(stackProperty.valueAttributes, attr, value);
+       },
+
+       /**
+        * Get default config value
+        * <code>savedValue<code> for installed services
+        * <code>initialValue<code> for new services
+        *
+        * @param configProperty
+        * @returns {*}
+        * @protected
+        */
+       _getInitialValue: function (configProperty) {
+               if (!configProperty) return null;
+               return this.useInitialValue(Em.get(configProperty, 
'serviceName')) ?
+                       Em.get(configProperty, 'initialValue') : 
Em.get(configProperty, 'savedValue');
+       },
+
+       /**
+        * Update initial only when <code>initialValue<code> is used
+        *
+        * @param {string} serviceName
+        * @returns {boolean}
+        */
+       updateInitialOnRecommendations: function(serviceName) {
+               return this.useInitialValue(serviceName);
+       },
+
+       /**
+        * Defines if initialValue of config can be used on current controller
+        * if not savedValue is used instead
+        *
+        * @param {String} serviceName
+        * @return {boolean}
+        */
+       useInitialValue: function (serviceName) {
+               return false;
+       },
+
+       /**
+        * Defines if recommendation allowed to be applied
+        *
+        * @param parentProperties
+        * @param name
+        * @param fileName
+        * @returns {boolean}
+        */
+       allowUpdateProperty: function (parentProperties, name, fileName) {
+               return true;
+       }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/mixins/common/configs/config_recommendations.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/config_recommendations.js 
b/ambari-web/app/mixins/common/configs/config_recommendations.js
new file mode 100644
index 0000000..583e86d
--- /dev/null
+++ b/ambari-web/app/mixins/common/configs/config_recommendations.js
@@ -0,0 +1,201 @@
+/**
+ * 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');
+
+/**
+ * @typedef {object} recommendation
+ * @property {boolean} saveRecommended - by default is true (checkbox binding)
+ * @property {boolean} saveRecommendedDefault - used for cancel operation to 
restore previous state (saved checkbox value)
+ * @property {boolean} isDeleted - true if property was deleted
+ * @property {boolean} notDefined - true if property was added
+ * @property {string} propertyName
+ * @property {string} propertyFileName - file name without '.xml'
+ * @property {string} configGroup - name of config group, by default "Default"
+ * @property {string} serviceName
+ * @property {string} serviceDisplayName
+ * @property {string} initialValue
+ * @property {string} recommendedValue
+ * @property {boolean} allowChangeGroup - flag that allows to change config 
group for config from dependent not default group
+ * @property {string[]} parentConfigs - list of properties based on which 
current recommendation was performed
+ */
+
+App.ConfigRecommendations = Em.Mixin.create({
+
+    /**
+     * List of recommendations that was applied to configs
+     *
+     * @type {recommendation[]}
+     */
+    recommendations: [],
+
+    /**
+     * Update recommendation property if exists
+     * otherwise add new
+     *
+     * @param {string} name
+     * @param {string} fileName
+     * @param {string} configGroupName
+     * @param {string} recommendedValue
+     * @param {string} initialValue
+     * @param {Object[]}parentProperties
+     * @returns {recommendation}
+     */
+    applyRecommendation: function(name, fileName, configGroupName, 
recommendedValue, initialValue, parentProperties) {
+        var parentPropertiesNames = parentProperties ? 
parentProperties.map(function(p) {
+            return App.config.configId(p.name, p.type);
+        }) : [];
+        var updated = this.updateRecommendation(name, fileName, 
configGroupName, recommendedValue, parentPropertiesNames);
+        if (!updated)
+            var added = this.addRecommendation(name, fileName, 
configGroupName, recommendedValue, initialValue, parentPropertiesNames);
+        return updated || added;
+    },
+
+    /**
+     * Add new recommendation
+     *
+     * @param {string} name
+     * @param {string} fileName
+     * @param {string} configGroupName
+     * @param {string} recommendedValue
+     * @param {string} initialValue
+     * @param {string[]} parentPropertiesNames
+     * @returns {recommendation}
+     */
+    addRecommendation: function(name, fileName, configGroupName, 
recommendedValue, initialValue, parentPropertiesNames) {
+        Em.assert('name and fileName should be defined', name && fileName);
+        var site = App.config.getConfigTagFromFileName(fileName);
+        var service = App.config.get('serviceByConfigTypeMap')[site];
+        var recommendation = {
+            saveRecommended: true,
+            saveRecommendedDefault: true,
+            propertyFileName: site,
+            propertyName: name,
+
+            isDeleted: Em.isNone(recommendedValue),
+            notDefined: Em.isNone(initialValue),
+
+            configGroup: configGroupName || "Default",
+            initialValue: initialValue,
+            parentConfigs: parentPropertiesNames || [],
+            serviceName: service.get('serviceName'),
+            allowChangeGroup: false,//TODO groupName!= "Default" && 
(service.get('serviceName') != this.get('selectedService.serviceName'))
+            //TODO&& 
(App.ServiceConfigGroup.find().filterProperty('serviceName', 
service.get('serviceName')).length > 1), //TODO
+            serviceDisplayName: service.get('displayName'),
+            recommendedValue: recommendedValue
+        };
+        this.get('recommendations').pushObject(recommendation);
+        return recommendation;
+    },
+
+    /**
+     * Remove recommendation
+     * based on unique identifiers
+     *
+     * @param {string} name
+     * @param {string} fileName
+     * @param {string} configGroupName
+     */
+    removeRecommendation: function(name, fileName, configGroupName) {
+        this.removeRecommendationObject(this.getRecommendation(name, fileName, 
configGroupName));
+    },
+
+    /**
+     * Remove recommended Object
+     *
+     * @param {recommendation} recommendation
+     */
+    removeRecommendationObject: function(recommendation) {
+        if (recommendation)
+            this.get('recommendations').removeObject(recommendation);
+    },
+
+    /**
+     * Update recommended object
+     *
+     * @param name
+     * @param fileName
+     * @param configGroupName
+     * @param recommendedValue
+     * @param parentPropertiesNames
+     * @returns {*|recommendation|null}
+     */
+    updateRecommendation: function(name, fileName, configGroupName, 
recommendedValue, parentPropertiesNames) {
+        var recommendation = this.getRecommendation(name, fileName, 
configGroupName);
+        if (recommendation) {
+            Em.set(recommendation, 'recommendedValue', recommendedValue);
+            if (parentPropertiesNames && parentPropertiesNames.length) {
+                var mergedProperties = 
parentPropertiesNames.concat(Em.get(recommendation, 'parentPropertiesNames'));
+                Em.set(recommendation, 'parentPropertiesNames', 
mergedProperties);
+            }
+        }
+        return recommendation;
+    },
+
+    /**
+     * Get single recommendation
+     *
+     * @param name
+     * @param fileName
+     * @param configGroupName
+     * @returns {recommendation|null}
+     */
+    getRecommendation: function(name, fileName, configGroupName) {
+        Em.assert('name and fileName should be defined', name && fileName);
+        return this.get('recommendations').find(function (dcv) {
+            return dcv.propertyName === name
+                && dcv.propertyFileName === 
App.config.getConfigTagFromFileName(fileName)
+                && dcv.configGroup === (configGroupName || "Default");
+        });
+    },
+
+    /**
+     * Clear recommendations that are
+     * same as initial value
+     *
+     * @method cleanUpRecommendations
+     */
+    cleanUpRecommendations: function() {
+        var cleanDependentList = 
this.get('recommendations').filter(function(d) {
+            return !((Em.isNone(d.initialValue) && 
Em.isNone(d.recommendedValue)) || d.initialValue == d.recommendedValue);
+        }, this);
+        this.set('recommendations', cleanDependentList);
+    },
+
+    /**
+     * Remove all recommendations
+     *
+     * @method clearAllRecommendations
+     */
+    clearAllRecommendations: function() {
+        this.set('recommendations', []);
+    },
+
+    /**
+     * Clear values for dependent configs for given services
+     *
+     * @method clearRecommendationsByServiceName
+     */
+    clearRecommendationsByServiceName: function(serviceNames) {
+        var filteredRecommendations = 
this.get('recommendations').reject(function(c) {
+            return serviceNames.contains(c.serviceName);
+        }, this);
+        this.set('recommendations', filteredRecommendations);
+    }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
 
b/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
new file mode 100644
index 0000000..5339637
--- /dev/null
+++ 
b/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
@@ -0,0 +1,113 @@
+/**
+ * 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.ConfigWithOverrideRecommendationParser = 
Em.Mixin.create(App.ConfigRecommendationParser, {
+
+       /**
+        * Method that goes through all configs
+        * and apply recommendations to overrides when it's needed
+        *
+        * @param {Object} recommendationObject
+        * @param {Object[]} configs
+        * @param {Object[]} parentProperties
+        * @param {App.ServiceConfigGroup} configGroup
+        */
+       updateOverridesByRecommendations: function (recommendationObject, 
configs, parentProperties, configGroup) {
+               Em.assert('Config groups should be defined and not default', 
configGroup && configGroup.get('name') && !configGroup.get('isDefault'));
+               this.parseRecommendations(recommendationObject, configs, 
parentProperties, configGroup,
+                       this._updateOverride.bind(this), 
this._removeOverride.bind(this), this._updateOverrideBoundaries.bind(this));
+       },
+
+       /**
+        * Update override by recommendations
+        * includes add/update actions
+        *
+        * @param config
+        * @param recommendedValue
+        * @param parentProperties
+        * @param configGroup
+        * @protected
+        */
+       _updateOverride: function(config, recommendedValue, parentProperties, 
configGroup) {
+               debugger;
+               var updateValue = this.allowUpdateProperty(parentProperties, 
Em.get(config, 'name'), Em.get(config, 'filename'));
+               var override = config.getOverride(configGroup.get('name'));
+               if (override) {
+                       this._updateConfigByRecommendation(override, 
recommendedValue, parentProperties);
+               } else if (updateValue) {
+                       this._addConfigOverrideRecommendation(config, 
recommendedValue, parentProperties, configGroup);
+               }
+       },
+
+       /**
+        * Remove override by recommendations
+        *
+        * @param property
+        * @param configs
+        * @param parentProperties
+        * @param configGroup
+        * @protected
+        */
+       _removeOverride: function(property, configs, parentProperties, 
configGroup) {
+               
this._removeConfigByRecommendation(property.getOverride(configGroup.get('name')),
 property.get('overrides') || [], parentProperties);
+       },
+
+       /**
+        * Add override by recommendations
+        *
+        * @param config
+        * @param recommendedValue
+        * @param configGroup
+        * @param parentProperties
+        * @protected
+        */
+       _addConfigOverrideRecommendation: function (config, recommendedValue, 
parentProperties, configGroup) {
+               var popupProperty = this.getRecommendation(Em.get(config, 
'name'), Em.get(config, 'filename'), configGroup.get('name')),
+                       initialValue = popupProperty ? popupProperty.value : 
null;
+               var coreObject = {
+                       "value": recommendedValue,
+                       "recommendedValue": recommendedValue,
+                       "initialValue": initialValue,
+                       "savedValue": !this.useInitialValue(Em.get(config, 
'serviceName')) && !Em.isNone(initialValue) ? initialValue : null,
+                       "isEditable": true
+               };
+               var override = App.config.createOverride(config, coreObject, 
configGroup);
+               configGroup.get('properties').pushObject(override);
+
+               this.applyRecommendation(Em.get(config, 'name'), Em.get(config, 
'filename'), configGroup.get('name'),
+                       recommendedValue, this._getInitialValue(override), 
parentProperties);
+       },
+
+       /**
+        * Update override valueAttributes by recommendations
+        *
+        * @param {Object} stackProperty
+        * @param {string} attr
+        * @param {Number|String|Boolean} value
+        * @param {App.ServiceConfigGroup} configGroup
+        * @protected
+        */
+       _updateOverrideBoundaries: function(stackProperty, attr, value, 
configGroup) {
+               if (!stackProperty.valueAttributes[configGroup.get('name')]) {
+                       stackProperty.valueAttributes[configGroup.get('name')] 
= {};
+               }
+               Em.set(stackProperty.valueAttributes[configGroup.get('name')], 
attr, value);
+       }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/mixins/common/configs/configs_saver.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/configs_saver.js 
b/ambari-web/app/mixins/common/configs/configs_saver.js
index 09cfd6f..383e4d0 100644
--- a/ambari-web/app/mixins/common/configs/configs_saver.js
+++ b/ambari-web/app/mixins/common/configs/configs_saver.js
@@ -620,7 +620,7 @@ App.ConfigsSaverMixin = Em.Mixin.create({
       App.QuickViewLinks.proto().loadTags();
     }
     this.showSaveConfigsPopup(header, flag, message, messageClass, value, 
status, urlParams);
-    this.clearDependentConfigs();
+    this.clearAllRecommendations();
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/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 7efcf55..0d3f20a 100644
--- a/ambari-web/app/mixins/common/configs/enhanced_configs.js
+++ b/ambari-web/app/mixins/common/configs/enhanced_configs.js
@@ -18,9 +18,8 @@
 
 var App = require('app');
 var blueprintUtils = require('utils/blueprint');
-var validator = require('utils/validator');
 
-App.EnhancedConfigsMixin = Em.Mixin.create({
+App.EnhancedConfigsMixin = 
Em.Mixin.create(App.ConfigWithOverrideRecommendationParser, {
 
   /**
    * this value is used for observing
@@ -49,17 +48,6 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
    */
   isControllerSupportsEnhancedConfigs: Em.computed.existsIn('name', 
['wizardStep7Controller','mainServiceInfoConfigsController']),
 
-  /**
-   * defines if initialValue of config can be used on current controller
-   * if not savedValue is used instead
-   * @param {String} serviceName
-   * @return {boolean}
-   * @method useInitialValue
-   */
-  useInitialValue: function(serviceName) {
-    return ['wizardStep7Controller'].contains(this.get('name')) && 
!App.Service.find().findProperty('serviceName', serviceName);
-  },
-
   dependenciesGroupMessage: 
Em.I18n.t('popup.dependent.configs.dependencies.for.groups'),
   /**
    * message fro alert box for dependent configs
@@ -75,39 +63,15 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
   }.property('changedProperties.length'),
 
   /**
-   * values for dependent configs
-   * @type {Object[]}
-   * ex:
-   * {
-   *   saveRecommended: {boolean}, //by default is true (checkbox binding)
-   *   saveRecommendedDefault: {boolean}, used for cancel operation to restore 
previous state
-   *   toDelete: {boolean} [true], // defines if property should be deleted
-   *   toAdd: {boolean} [false], // defines if property should be added
-   *   isDeleted: {boolean} [true], // defines if property was deleted, but 
was present in initial configs
-   *   fileName: {string}, //file name without '.xml'
-   *   propertyName: {string},
-   *   parentConfigs: {string[]} // name of the parent configs
-   *   configGroup: {string},
-   *   value: {string},
-   *   serviceName: {string},
-   *   allowChangeGroup: {boolean}, //used to disable group link for current 
service
-   *   serviceDisplayName: {string},
-   *   recommendedValue: {string}
-   * }
-   * @private
-   */
-  _dependentConfigValues: Em.A([]),
-
-  /**
    * dependent properties that was changed by Ambari
    * @type {Object[]}
    */
   changedProperties: function() {
-    return this.get('_dependentConfigValues').filter(function(dp) {
+    return this.get('recommendations').filter(function(dp) {
       return (this.get('selectedConfigGroup.isDefault') && Em.get(dp, 
'configGroup').contains('Default'))
         || [this.get('selectedConfigGroup.name'), 
this.get('selectedConfigGroup.dependentConfigGroups') && 
this.get('selectedConfigGroup.dependentConfigGroups')[Em.get(dp, 
'serviceName')]].contains(Em.get(dp, 'configGroup'));
     }, this);
-  }.property('[email protected]', 
'selectedConfigGroup'),
+  }.property('[email protected]', 
'[email protected]', 'selectedConfigGroup'),
 
   /**
    * defines if change dependent group message should be shown
@@ -143,67 +107,6 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
   /******************************METHODS THAT WORKS WITH DEPENDENT CONFIGS 
*************************************/
 
   /**
-   * clear values for dependent configs
-   * @method clearDependentConfigs
-   * @private
-   */
-  clearDependentConfigs: function() {
-    this.setProperties({
-      _dependentConfigValues: []
-    });
-  },
-
-  /**
-   * clear values for dependent configs for given services
-   * @method clearDependentConfigs
-   * @private
-   */
-  clearDependentConfigsByService: function(serviceNames) {
-    var cleanDependencies = 
this.get('_dependentConfigValues').reject(function(c) {
-      return serviceNames.contains(c.serviceName);
-    }, this);
-    this.get('stepConfigs').filter(function(s) {
-      return serviceNames.contains(s.get('serviceName'));
-    }).forEach(function(s) {
-      s.get('configs').setEach('isNotSaved', false);
-    });
-    this.set('_dependentConfigValues', cleanDependencies);
-  },
-
-  /**
-   * Remove configs from <code>_dependentConfigValues</code> which depends 
between installed services only.
-   *
-   * @param {String[]} installedServices
-   * @param {App.ServiceConfig[]} stepConfigs
-   */
-  clearDependenciesForInstalledServices: function(installedServices, 
stepConfigs) {
-    var allConfigs = 
stepConfigs.mapProperty('configs').filterProperty('length').reduce(function(p, 
c) {
-      return p && p.concat(c);
-    });
-    var cleanDependencies = 
this.get('_dependentConfigValues').reject(function(item) {
-      if (Em.get(item, 'propertyName').contains('hadoop.proxyuser')) return 
false;
-      if (installedServices.contains(Em.get(item, 'serviceName'))) {
-        var stackProperty = 
App.configsCollection.getConfigByName(item.propertyName, item.fileName);
-        var parentConfigs = stackProperty && stackProperty.propertyDependsOn;
-        if (!parentConfigs || !parentConfigs.length) {
-          return true;
-        }
-        // check that all parent properties from installed service
-        return !parentConfigs.reject(function(parentConfig) {
-          var property = allConfigs.filterProperty('filename', 
App.config.getOriginalFileName(parentConfig.type))
-                                   .findProperty('name', parentConfig.name);
-          if (!property) {
-            return false;
-          }
-          return installedServices.contains(Em.get(property, 'serviceName'));
-        }).length;
-      }
-      return false;
-    });
-    this.set('_dependentConfigValues', cleanDependencies);
-  },
-
-  /**
    * get config group object for current service
    * @param serviceName
    * @returns {App.ConfigGroup|null}
@@ -236,9 +139,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
    * @method removeCurrentFromDependentList
    */
   removeCurrentFromDependentList: function (config, saveRecommended) {
-    var current = 
this.get('_dependentConfigValues').find(function(dependentConfig) {
-      return Em.get(dependentConfig, 'propertyName') == config.get('name') && 
Em.get(dependentConfig, 'fileName') == 
App.config.getConfigTagFromFileName(config.get('filename'));
-    });
+    var current = this.getRecommendation(config.get('name'), 
config.get('filename'), config.get('group.name'));
     if (current) {
       Em.setProperties(current, {
           'saveRecommended': !!saveRecommended,
@@ -265,7 +166,8 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
         hosts: this.get('hostNames'),
         services: this.get('serviceNames')
       };
-      var clearConfigsOnAddService = this.isConfigHasInitialState();
+
+      var clearConfigsOnAddService = configGroup.get('isDefault') && 
this.isConfigHasInitialState();
       if (clearConfigsOnAddService) {
         recommendations.blueprint.configurations = 
this.get('initialConfigValues');
       } else {
@@ -287,7 +189,6 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
           stackVersionUrl: App.get('stackVersionURL'),
           dataToSend: dataToSend,
           notDefaultGroup: configGroup && !configGroup.get('isDefault'),
-          initial: initial,
           clearConfigsOnAddService: clearConfigsOnAddService
         },
         success: 'dependenciesSuccess',
@@ -313,7 +214,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
     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);
+          return App.config.configId(changed.propertyName, 
changed.propertyFileName);
         }).contains(App.config.configId(c.get('name'), c.get('filename')));
       }, this).length;
     }, this).length;
@@ -326,18 +227,16 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
   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'));
-        });
+        var recommendedProperty = this.getRecommendation(c.get('name'), 
c.get('filename'), c.get('group.name'));
         if (recommendedProperty) {
-          var initialValue = recommendedProperty.value;
+          var initialValue = recommendedProperty.initialValue;
           if (Em.isNone(initialValue)) {
             stepConfig.get('configs').removeObject(c);
           } else {
+            c.set('initialValue', initialValue);
             c.set('value', initialValue);
-            c.set('recommendedValue', initialValue);
           }
-          this.get('_dependentConfigValues').removeObject(recommendedProperty);
+          this.removeRecommendationObject(recommendedProperty);
         }
       }, this)
     }, this);
@@ -379,13 +278,11 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
    * @method dependenciesSuccess
    */
   dependenciesSuccess: function (data, opt, params) {
-    this._saveRecommendedValues(data, params.initial, 
params.dataToSend.changed_configurations, params.notDefaultGroup);
+    this._saveRecommendedValues(data, 
params.dataToSend.changed_configurations, params.notDefaultGroup);
     this.set("recommendationsConfigs", Em.get(data.resources[0] , 
"recommendations.blueprint.configurations"));
     if (params.clearConfigsOnAddService) {
-      if (this.get('wizardController.name') == 'addServiceController') {
-        
this.clearDependenciesForInstalledServices(this.get('installedServiceNames'), 
this.get('stepConfigs'));
-      }
       this.clearConfigValues();
+      this.clearAllRecommendations();
     }
     this.set('recommendationTimeStamp', (new Date).getTime());
   },
@@ -395,7 +292,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
    * @method showChangedDependentConfigs
    */
   showChangedDependentConfigs: function(event, callback, secondary) {
-    if (this.get('_dependentConfigValues.length') > 0) {
+    if (this.get('recommendations.length') > 0) {
       App.showDependentConfigsPopup(this.get('changedProperties'), 
this.onSaveRecommendedPopup.bind(this), secondary);
     } else {
       if (callback) {
@@ -413,23 +310,32 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
    */
   undoRedoRecommended: function(propertiesToUpdate, redo) {
     propertiesToUpdate.forEach(function(p) {
-      var initial = redo ? Em.get(p, 'value') : Em.get(p, 'recommendedValue');
-      var recommended = redo ? Em.get(p, 'recommendedValue') : Em.get(p, 
'value');
+      var initial = redo ? Em.get(p, 'initialValue') : Em.get(p, 
'recommendedValue');
+      var recommended = redo ? Em.get(p, 'recommendedValue') : Em.get(p, 
'initialValue');
       var stepConfig = this.get('stepConfigs').findProperty('serviceName', 
Em.get(p, 'serviceName'));
       var config = stepConfig.get('configs').find(function(scp) {
-        return scp.get('name') == Em.get(p, 'propertyName') && 
scp.get('filename') == Em.get(p, 'fileName');
+        return scp.get('name') == Em.get(p, 'propertyName') && 
scp.get('filename') == App.config.getOriginalFileName(Em.get(p, 
'propertyFileName'));
       });
       var selectedGroup = 
App.ServiceConfigGroup.find().filterProperty('serviceName', Em.get(p, 
'serviceName')).findProperty('name', Em.get(p, 'configGroup'));
-      if (Em.isNone(recommended)) {
-        if (selectedGroup.get('isDefault')) {
+      if (selectedGroup.get('isDefault')) {
+        if (Em.isNone(recommended)) {
           stepConfig.get('configs').removeObject(config);
+        } else if (Em.isNone(initial)) {
+          this._addConfigByRecommendation(stepConfig.get('configs'), Em.get(p, 
'propertyName'), Em.get(p, 'propertyFileName'), recommended);
         } else {
-          config.get('overrides').removeObject(this._getOverride(config, 
selectedGroup));
+          Em.set(config, 'value', recommended);
         }
-      } else if (Em.isNone(initial)) {
-        this._addConfigByRecommendation(stepConfig, selectedGroup, Em.get(p, 
'propertyName'), Em.get(p, 'fileName'), Em.get(p, 'serviceName'), recommended, 
initial, config);
       } else {
-        Em.set(config, 'value', recommended);
+        if (Em.isNone(recommended)) {
+          
config.get('overrides').removeObject(config.getOverride(selectedGroup.get('name')));
+        } else if (Em.isNone(initial)) {
+          this._addConfigOverrideRecommendation(config, recommended, null, 
selectedGroup);
+        } else {
+          var override = config.getOverride(selectedGroup.get('name'));
+          if (override) {
+            override.set('value', recommended);
+          }
+        }
       }
     }, this);
   },
@@ -451,7 +357,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
     }, this);
     App.showSelectGroupsPopup(this.get('selectedService.serviceName'),
       this.get('selectedService.configGroups').findProperty('name', 
this.get('selectedConfigGroup.name')),
-      dependentServices, this.get('_dependentConfigValues'))
+      dependentServices, this.get('recommendations'))
   },
 
   /**
@@ -467,72 +373,33 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
   },
 
   /**
-   * saves values from response for dependent config properties to 
<code>_dependentConfigValues<code>
+   * saves values from response for dependent config properties to 
<code>recommendations<code>
    * @param data
-   * @param [updateOnlyBoundaries=false]
    * @param [changedConfigs=null]
    * @param notDefaultGroup
-   * @param updateInitial
    * @method saveRecommendedValues
    * @private
    */
-  _saveRecommendedValues: function(data, updateOnlyBoundaries, changedConfigs, 
notDefaultGroup, updateInitial) {
+  _saveRecommendedValues: function(data, changedConfigs, notDefaultGroup) {
     Em.assert('invalid data - 
`data.resources[0].recommendations.blueprint.configurations` not defined ', 
data && data.resources[0] && Em.get(data.resources[0], 
'recommendations.blueprint.configurations'));
     var configObject = 
data.resources[0].recommendations.blueprint.configurations;
     if (!notDefaultGroup) {
-      this.parseConfigsByTag(configObject, changedConfigs, updateInitial, 
updateOnlyBoundaries);
-    } else if (data.resources[0].recommendations['config-groups']){
+      this.get('stepConfigs').forEach(function(stepConfig) {
+        this.updateConfigsByRecommendations(configObject, 
stepConfig.get('configs'), changedConfigs);
+      }, this);
+      this.addByRecommendations(configObject, changedConfigs);
+    } else if (data.resources[0].recommendations['config-groups']) {
       var configFroGroup = 
data.resources[0].recommendations['config-groups'][0];
-      this.parseConfigsByTag(configFroGroup.configurations, changedConfigs, 
updateInitial, updateOnlyBoundaries);
-      this.parseConfigsByTag(configFroGroup.dependent_configurations, 
changedConfigs, updateInitial, updateOnlyBoundaries);
-    }
-    this._cleanUpPopupProperties();
-  },
-
-  /**
-   * saves values from response for dependent configs to 
<code>_dependentConfigValues<code>
-   * @param configObject - JSON response from `recommendations` endpoint
-   * @param {App.ServiceConfigProperty[]} parentConfigs - config properties 
for which recommendations were received
-   * @param updateInitial
-   * @param updateOnlyBoundaries
-   * @method saveRecommendedValues
-   * @private
-   */
-  parseConfigsByTag: function(configObject, parentConfigs, updateInitial, 
updateOnlyBoundaries) {
-    var parentPropertiesNames = parentConfigs ? parentConfigs.map(function(p) 
{ return App.config.configId(Em.get(p, 'name'), Em.get(p, 'type'))}) : [];
-    /** get all configs by config group **/
-    for (var key in configObject) {
-
-      /**  defines main info for file name (service name, config group, config 
that belongs to filename) **/
-      var service = App.config.get('serviceByConfigTypeMap')[key];
-      var serviceName = service.get('serviceName');
-      var stepConfig = this.get('stepConfigs').findProperty('serviceName', 
serviceName);
-      if (stepConfig) {
-        var configProperties = stepConfig ? 
stepConfig.get('configs').filterProperty('filename', 
App.config.getOriginalFileName(key)) : [];
-
-        var group = this.getGroupForService(serviceName);
-
-        for (var propertyName in configObject[key].properties) {
-
-          var cp = configProperties.findProperty('name', propertyName);
-
-          var configPropertyObject = (!group || group.get('isDefault')) ? cp : 
this._getOverride(cp, group);
-
-          var recommendedValue = 
this.getFormattedValue(configObject[key].properties[propertyName]);
-          var popupProperty = this.getPopupProperty(propertyName, key, 
Em.get(group || {}, 'name'));
-          var initialValue = this._getInitialValue(configObject, 
popupProperty, serviceName, recommendedValue, updateInitial);
-          if (configPropertyObject) {
-            this._updateConfigByRecommendation(configPropertyObject, 
recommendedValue, updateInitial, updateOnlyBoundaries);
-          } else if (!updateOnlyBoundaries) {
-            this._addConfigByRecommendation(stepConfig, group, propertyName, 
key, serviceName, recommendedValue, initialValue, cp);
-          }
-          if (!updateOnlyBoundaries) {
-            this._updatePopup(popupProperty, propertyName, key, 
recommendedValue, Em.get(configPropertyObject || {}, 'initialValue'), service, 
Em.get(group || {},'name') || "Default", parentPropertiesNames);
-          }
+      this.get('stepConfigs').forEach(function(stepConfig) {
+        var configGroup = 
this.getGroupForService(stepConfig.get('serviceName'));
+        if (configGroup) {
+          this.updateOverridesByRecommendations(configFroGroup.configurations, 
stepConfig.get('configs'), changedConfigs, configGroup);
+          
this.updateOverridesByRecommendations(configFroGroup.dependent_configurations, 
stepConfig.get('configs'), changedConfigs, configGroup);
+          this.toggleProperty('forceUpdateBoundaries');
         }
-      }
+      }, this);
     }
-    this.parseConfigAttributes(configObject, parentPropertiesNames, 
updateOnlyBoundaries);
+    this.cleanUpRecommendations();
   },
 
   installedServices: function () {
@@ -542,241 +409,6 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
   }.property(),
 
   /**
-   * Save property attributes received from recommendations. These attributes 
are minimum, maximum,
-   * increment_step. Attributes are stored in 
<code>App.StackConfigProperty</code> model.
-   *
-   * @param {Object[]} configs
-   * @param parentPropertiesNames
-   * @param updateOnlyBoundaries
-   * @private
-   */
-  parseConfigAttributes: function(configs, parentPropertiesNames, 
updateOnlyBoundaries) {
-    var self = this;
-    Em.keys(configs).forEach(function (siteName) {
-      var fileName = App.config.getOriginalFileName(siteName),
-        service = App.config.get('serviceByConfigTypeMap')[siteName];
-      var serviceName = service && service.get('serviceName'),
-        stepConfig = self.get('stepConfigs').findProperty('serviceName', 
serviceName);
-          if (stepConfig) {
-            var group = self.getGroupForService(serviceName),
-                configProperties = stepConfig ? 
stepConfig.get('configs').filterProperty('filename', 
App.config.getOriginalFileName(siteName)) : [],
-                properties = configs[siteName].property_attributes || {};
-            Em.keys(properties).forEach(function (propertyName) {
-              var cp = configProperties.findProperty('name', propertyName);
-              var stackProperty = 
App.configsCollection.getConfigByName(propertyName, siteName);
-              var configObject = (!group || group.get('isDefault')) ? cp : 
self._getOverride(cp, group);
-              var configsCollection = !group || group.get('isDefault') ? 
stepConfig.get('configs') : Em.getWithDefault(cp, 'overrides', []);
-              var dependentProperty = self.getPopupProperty(propertyName, 
fileName, Em.get(group || {},'name'));
-              var attributes = properties[propertyName] || {};
-              Em.keys(attributes).forEach(function (attributeName) {
-                if (attributeName == 'delete' && configObject) {
-                  if (!updateOnlyBoundaries) {
-                    self._removeConfigByRecommendation(configObject, 
configsCollection);
-                    self._updatePopup(dependentProperty, propertyName, 
siteName, null, Em.get(configObject, 'initialValue'), service, Em.get(group || 
{},'name') || "Default", parentPropertiesNames);
-                  }
-                } else if (stackProperty) {
-                  var selectedConfigGroup = group && !group.get('isDefault') ? 
group.get('name') : null;
-                  if (selectedConfigGroup) {
-                    if (!stackProperty.valueAttributes[selectedConfigGroup]) {
-                      /** create not default group object for updating such 
values as min/max **/
-                      Em.set(stackProperty.valueAttributes, 
selectedConfigGroup, {});
-                    }
-                    if 
(stackProperty.valueAttributes[selectedConfigGroup][attributeName] != 
attributes[attributeName]) {
-                      
Em.set(stackProperty.valueAttributes[selectedConfigGroup], attributeName, 
attributes[attributeName]);
-                      self.toggleProperty('forceUpdateBoundaries');
-                    }
-                  } else {
-                    Em.set(stackProperty.valueAttributes, attributeName, 
attributes[attributeName]);
-                  }
-                }
-              });
-            });
-      }
-    });
-  },
-
-  /**
-   * update config based on recommendations
-   * @param config
-   * @param recommendedValue
-   * @param updateInitial
-   * @param updateOnlyBoundaries
-   * @private
-   */
-  _updateConfigByRecommendation: function(config, recommendedValue, 
updateInitial, updateOnlyBoundaries) {
-    Em.assert('config should be defined', config);
-    Em.set(config, 'recommendedValue', recommendedValue);
-    if (!updateOnlyBoundaries) Em.set(config, 'value', recommendedValue);
-    if (updateInitial && Em.isNone(Em.get(config, 'savedValue'))) 
Em.set(config, 'initialValue', recommendedValue);
-  },
-
-  /**
-   * remove config based on recommendations
-   * @param config
-   * @param configsCollection
-   * @private
-   */
-  _removeConfigByRecommendation: function(config, configsCollection) {
-    Em.assert('config and configsCollection should be defined', config && 
configsCollection);
-    configsCollection.removeObject(config);
-    /**
-     * need to update wizard info when removing configs for installed services;
-     */
-    var installedServices = this.get('installedServices'), wizardController = 
this.get('wizardController'),
-        fileNamesToUpdate = wizardController ? 
wizardController.getDBProperty('fileNamesToUpdate') || [] : [],
-        fileName = Em.get(config, 'filename'), serviceName = Em.get(config, 
'serviceName');
-    var modifiedFileNames = this.get('modifiedFileNames');
-    if (modifiedFileNames && !modifiedFileNames.contains(fileName)) {
-      modifiedFileNames.push(fileName);
-    } else if (wizardController && installedServices[serviceName]) {
-      if (!fileNamesToUpdate.contains(fileName)) {
-        fileNamesToUpdate.push(fileName);
-      }
-    }
-    if (wizardController) {
-      wizardController.setDBProperty('fileNamesToUpdate', 
fileNamesToUpdate.uniq());
-    }
-  },
-
-  /**
-   * add config based on recommendations
-   * @param stepConfigs
-   * @param selectedGroup
-   * @param name
-   * @param fileName
-   * @param serviceName
-   * @param recommendedValue
-   * @param initialValue
-   * @param cp
-   * @private
-   */
-  _addConfigByRecommendation: function(stepConfigs, selectedGroup, name, 
fileName, serviceName, recommendedValue, initialValue, cp) {
-    fileName = App.config.getOriginalFileName(fileName);
-    var coreObject = {
-      "value": recommendedValue,
-      "recommendedValue": recommendedValue,
-      "initialValue": initialValue,
-      "savedValue": !this.useInitialValue(serviceName) && 
!Em.isNone(initialValue) ? initialValue : null,
-      "isEditable": true
-    };
-    if (!selectedGroup || selectedGroup.get('isDefault')) {
-      var addedProperty = App.configsCollection.getConfigByName(name, 
fileName) || App.config.createDefaultConfig(name, serviceName, fileName, false, 
coreObject);
-      var addedPropertyObject = 
App.ServiceConfigProperty.create(addedProperty);
-      stepConfigs.get('configs').pushObject(addedPropertyObject);
-      addedPropertyObject.validate();
-    } else {
-      if (cp) {
-        var newOverride = App.config.createOverride(cp, coreObject, 
selectedGroup);
-        selectedGroup.get('properties').pushObject(newOverride);
-      } else {
-        
stepConfigs.get('configs').push(App.config.createCustomGroupConfig(name, 
fileName, recommendedValue, selectedGroup, true, true));
-      }
-    }
-  },
-
-  /**
-   * @param configProperty
-   * @param popupProperty
-   * @param serviceName
-   * @param recommendedValue
-   * @param updateInitial
-   * @returns {*}
-   * @private
-   */
-  _getInitialValue: function(configProperty, popupProperty, serviceName, 
recommendedValue, updateInitial) {
-    if (!this.useInitialValue(serviceName)) {
-      return configProperty ? Em.get(configProperty, 'savedValue') : null;
-    } else if (updateInitial) {
-      return recommendedValue;
-    } else {
-      return popupProperty ? popupProperty.value : configProperty ? 
Em.get(configProperty, 'initialValue') : null;
-    }
-  },
-
-  /**
-   * format value for float values
-   * @param value
-   * @returns {*}
-   */
-  getFormattedValue: function(value) {
-    return validator.isValidFloat(value) ? parseFloat(value).toString() : 
value;
-  },
-
-  /**
-   * just get config override
-   * @param cp
-   * @param selectedGroup
-   * @returns {*|Object}
-   * @private
-   */
-  _getOverride: function(cp, selectedGroup) {
-    return Em.get(cp, 'overrides.length') && Em.get(cp, 
'overrides').findProperty('group.name', Em.get(selectedGroup, 'name'));
-  },
-
-  /**
-   * get property form popup
-   * @param name
-   * @param fileName
-   * @param groupName
-   * @returns {Object}
-   */
-  getPopupProperty: function(name, fileName, groupName) {
-    return this.get('_dependentConfigValues').find(function (dcv) {
-      return dcv.propertyName === name && dcv.fileName === 
App.config.getOriginalFileName(fileName) && dcv.configGroup === (groupName || 
"Default");
-    });
-  },
-
-  /**
-   * add or update proeprty in popup
-   * @param popupProperty
-   * @param name
-   * @param fileName
-   * @param recommendedValue
-   * @param initialValue
-   * @param service
-   * @param groupName
-   * @param parentPropertiesNames
-   * @private
-   */
-  _updatePopup: function(popupProperty, name, fileName, recommendedValue, 
initialValue, service, groupName, parentPropertiesNames) {
-    if (popupProperty) {
-      Em.set(popupProperty, 'recommendedValue', recommendedValue);
-      Em.set(popupProperty, 'isDeleted', Em.isNone(recommendedValue));
-    } else {
-      var popupPropertyObject = {
-        saveRecommended: true,
-        saveRecommendedDefault: true,
-        fileName: App.config.getOriginalFileName(fileName),
-        propertyName: name,
-
-        isDeleted: Em.isNone(recommendedValue),
-        notDefined: Em.isNone(initialValue),
-
-        configGroup: groupName,
-        value: initialValue,
-        parentConfigs: parentPropertiesNames,
-        serviceName: service.get('serviceName'),
-        allowChangeGroup: groupName!= "Default" && (service.get('serviceName') 
!= this.get('selectedService.serviceName'))
-          && (App.ServiceConfigGroup.find().filterProperty('serviceName', 
service.get('serviceName')).length > 1),
-        serviceDisplayName: service.get('displayName'),
-        recommendedValue: recommendedValue
-      };
-      this.get('_dependentConfigValues').pushObject(popupPropertyObject);
-    }
-  },
-
-  /**
-   * clean properties that have same current and recommended values
-   * @private
-   */
-  _cleanUpPopupProperties: function() {
-    var cleanDependentList = 
this.get('_dependentConfigValues').filter(function(d) {
-      return !((Em.isNone(d.value) && Em.isNone(d.recommendedValue)) || 
d.value == d.recommendedValue);
-    }, this);
-    this.set('_dependentConfigValues', cleanDependentList);
-  },
-
-  /**
    * Helper method to get property from the <code>stepConfigs</code>
    *
    * @param {String} name - config property name

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/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 7938729..40dd054 100644
--- a/ambari-web/app/mixins/common/serverValidator.js
+++ b/ambari-web/app/mixins/common/serverValidator.js
@@ -174,7 +174,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
    * @param data
    */
   loadRecommendationsSuccess: function(data) {
-    this._saveRecommendedValues(data, false, null, false, true);
+    this._saveRecommendedValues(data, null, false);
     this.set("recommendationsConfigs", Em.get(data.resources[0] , 
"recommendations.blueprint.configurations"));
     this.set('recommendationTimeStamp', (new Date).getTime());
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/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 2bc151b..56b8aa4 100644
--- a/ambari-web/app/models/configs/objects/service_config.js
+++ b/ambari-web/app/models/configs/objects/service_config.js
@@ -59,6 +59,10 @@ App.ServiceConfig = Ember.Object.extend({
     }, this);
   }.observes('configsWithErrors'),
 
+  configTypes: function() {
+    return 
App.StackService.find(this.get('serviceName')).get('configTypeList') || [];
+  }.property('serviceName'),
+
   observeForeignKeys: function() {
     //TODO refactor or move this logic to other place
     var configs = this.get('configs');

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/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 3a4ca3d..4b48a98 100644
--- a/ambari-web/app/models/configs/objects/service_config_property.js
+++ b/ambari-web/app/models/configs/objects/service_config_property.js
@@ -506,6 +506,20 @@ App.ServiceConfigProperty = Em.Object.extend({
   }.property('displayType', 'name', 'App.isHadoop22Stack'),
 
   /**
+   * Get override for selected group
+   *
+   * @param {String} groupName
+   * @returns {App.ServiceConfigProperty|null}
+   */
+  getOverride: function(groupName) {
+    Em.assert('Group name should be defined string', (typeof groupName === 
'string') && groupName);
+    if (this.get('overrides.length')) {
+      return this.get('overrides').findProperty('group.name', groupName);
+    }
+    return null;
+  },
+
+  /**
    * Update description for `password`-config
    * Add extra-message about their comparison
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/routes/add_service_routes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/add_service_routes.js 
b/ambari-web/app/routes/add_service_routes.js
index 35b06ab..30bdcbc 100644
--- a/ambari-web/app/routes/add_service_routes.js
+++ b/ambari-web/app/routes/add_service_routes.js
@@ -199,7 +199,7 @@ module.exports = App.WizardRoute.extend({
             recommendationsConfigs: null
           });
           router.get('wizardStep7Controller').set('recommendationsConfigs', 
null);
-          router.get('wizardStep7Controller').clearDependentConfigs();
+          router.get('wizardStep7Controller').clearAllRecommendations();
           router.transitionTo('step4');
         });
       });

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs 
b/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs
index ca62592..cef7be2 100644
--- a/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs
+++ b/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs
@@ -44,12 +44,12 @@
             {{config.configGroup}}
           </a></span>
         </td>
-        <td class="config-dependency-filename">{{config.fileName}}</td>
+        <td class="config-dependency-filename">{{config.propertyFileName}}</td>
         <td class="config-dependency-value">
           {{#if config.notDefined}}
             <i>{{t popup.dependent.configs.table.not.defined}}</i>
           {{else}}
-            {{config.value}}
+            {{config.initialValue}}
           {{/if}}
         </td>
         <td class="config-dependency-recommended-value">

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/utils/config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js
index f4c8034..a533994 100644
--- a/ambari-web/app/utils/config.js
+++ b/ambari-web/app/utils/config.js
@@ -19,6 +19,7 @@
 var App = require('app');
 require('utils/configs_collection');
 var stringUtils = require('utils/string_utils');
+var validator = require('utils/validator');
 
 var configTagFromFileNameMap = {};
 
@@ -212,7 +213,7 @@ App.config = Em.Object.create({
    */
   getServiceByConfigType: function(configType) {
     return App.StackService.find().find(function(s) {
-      return Object.keys(s.get('configTypes')).contains(configType);
+      return s.get('configTypeList').contains(configType);
     });
   },
 
@@ -495,6 +496,29 @@ App.config = Em.Object.create({
   },
 
   /**
+   * Format float value
+   *
+   * @param {*} value
+   * @returns {string|*}
+   */
+  formatValue: function(value) {
+    return validator.isValidFloat(value) ? parseFloat(value).toString() : 
value;
+  },
+
+  /**
+   * Get step config by file name
+   *
+   * @param stepConfigs
+   * @param fileName
+   * @returns {Object|null}
+   */
+  getStepConfigForProperty: function (stepConfigs, fileName) {
+    return stepConfigs.find(function (s) {
+      return 
s.get('configTypes').contains(App.config.getConfigTagFromFileName(fileName));
+    });
+  },
+
+  /**
    *
    * @param configs
    * @returns {Object[]}

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/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 a88be76..367a7ee 100644
--- a/ambari-web/app/views/common/controls_view.js
+++ b/ambari-web/app/views/common/controls_view.js
@@ -113,9 +113,9 @@ App.SupportsDependentConfigs = Ember.Mixin.create({
    */
   restoreDependentConfigs: function(parentConfig) {
     var controller = this.get('controller');
-    var dependentConfigs = controller.get('_dependentConfigValues');
+    var dependentConfigs = controller.get('recommendations');
     try {
-      controller.set('_dependentConfigValues', 
dependentConfigs.reject(function(item) {
+      controller.set('recommendations', dependentConfigs.reject(function(item) 
{
         if (item.parentConfigs.contains(parentConfig.get('name'))) {
           if (item.parentConfigs.length > 1) {
             item.parentConfigs.removeObject(parentConfig.get('name'));

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/app/views/common/modal_popups/select_groups_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/modal_popups/select_groups_popup.js 
b/ambari-web/app/views/common/modal_popups/select_groups_popup.js
index 264d7b1..33c72a2 100644
--- a/ambari-web/app/views/common/modal_popups/select_groups_popup.js
+++ b/ambari-web/app/views/common/modal_popups/select_groups_popup.js
@@ -64,7 +64,7 @@ App.showSelectGroupsPopup = function (selectedServiceName, 
selectedConfigGroup,
         var currentGroupName = this.get('selectedGroups')[serviceName] || "";
         var configGroup = 
this.get('dependentStepConfigs').findProperty('serviceName', 
serviceName).get('configGroups').findProperty('name', selectedGroupName);
         if (selectedGroupName != currentGroupName) {
-          /** changing config group for _dependentConfigValues **/
+          /** changing config group for recommendations **/
           configs.filterProperty('serviceName', 
serviceName).filterProperty('configGroup', selectedGroupName).forEach(function 
(c) {
             if (configs.filterProperty('serviceName', 
serviceName).filterProperty('configGroup', currentGroupName)) {
               configs.removeObject(c);

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/test/controllers/main/service/info/config_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service/info/config_test.js 
b/ambari-web/test/controllers/main/service/info/config_test.js
index b6abb8e..ba8f1d3 100644
--- a/ambari-web/test/controllers/main/service/info/config_test.js
+++ b/ambari-web/test/controllers/main/service/info/config_test.js
@@ -376,9 +376,9 @@ describe("App.MainServiceInfoConfigsController", function 
() {
 
     it("should clear dependent configs", function() {
       mainServiceInfoConfigsController.set('groupsToSave', { HDFS: 'my cool 
group'});
-      mainServiceInfoConfigsController.set('_dependentConfigValues', 
Em.A([{name: 'prop_1'}]));
+      mainServiceInfoConfigsController.set('recommendations', Em.A([{name: 
'prop_1'}]));
       mainServiceInfoConfigsController.doCancel();
-      
expect(App.isEmptyObject(mainServiceInfoConfigsController.get('_dependentConfigValues'))).to.be.true;
+      
expect(App.isEmptyObject(mainServiceInfoConfigsController.get('recommendations'))).to.be.true;
     });
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/configs/enhanced_configs_test.js 
b/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
index 1b7115c..3ec4b07 100644
--- a/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
+++ b/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
@@ -24,19 +24,21 @@ describe('App.EnhancedConfigsMixin', function() {
   var instanceObject = mixinObject.create({});
   describe('#removeCurrentFromDependentList()', function() {
     it('update some fields', function() {
-      instanceObject.get('_dependentConfigValues').pushObject({
+      instanceObject.get('recommendations').pushObject({
           saveRecommended: true,
           saveRecommendedDefault: true,
+          configGroup: "Default",
           propertyName: 'p1',
-          fileName: 'f1',
+          propertyFileName: 'f1',
           value: 'v1'
         });
       instanceObject.removeCurrentFromDependentList(Em.Object.create({name: 
'p1', filename: 'f1.xml', value: 'v2'}));
-      expect(instanceObject.get('_dependentConfigValues')[0]).to.eql({
+      expect(instanceObject.get('recommendations')[0]).to.eql({
         saveRecommended: false,
         saveRecommendedDefault: false,
+        configGroup: "Default",
         propertyName: 'p1',
-        fileName: 'f1',
+        propertyFileName: 'f1',
         value: 'v1'
       });
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/73a850eb/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js
----------------------------------------------------------------------
diff --git 
a/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js 
b/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js
index e7f979b..ed43a1b 100644
--- a/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js
+++ b/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js
@@ -209,22 +209,22 @@ describe('App.ConfigWidgetView', function () {
 
     tests.forEach(function(test) {
       it(test.m, function() {
-        view.set('controller._dependentConfigValues', test.dependentConfigs);
+        view.set('controller.recommendations', test.dependentConfigs);
         view.restoreDependentConfigs(view.get('config'));
-        
expect(view.get('controller._dependentConfigValues').mapProperty('name')).to.be.eql(test.e);
+        
expect(view.get('controller.recommendations').mapProperty('name')).to.be.eql(test.e);
       });
     });
 
     it('when dependent configs has multiple parents appropriate parent config 
should be removed', function() {
-      view.set('controller._dependentConfigValues', [
+      view.set('controller.recommendations', [
         {name: 'dependent1', parentConfigs: ['config1', 'config2']},
         {name: 'dependent2', parentConfigs: ['config2', 'config1']},
         {name: 'dependent3', parentConfigs: ['config1']}
       ]);
       view.restoreDependentConfigs(view.get('config'));
-      
expect(view.get('controller._dependentConfigValues').findProperty('name', 
'dependent1').parentConfigs.toArray()).to.be.eql(["config2"]);
-      
expect(view.get('controller._dependentConfigValues').findProperty('name', 
'dependent2').parentConfigs.toArray()).to.be.eql(["config2"]);
-      
expect(view.get('controller._dependentConfigValues.length')).to.be.eql(2);
+      expect(view.get('controller.recommendations').findProperty('name', 
'dependent1').parentConfigs.toArray()).to.be.eql(["config2"]);
+      expect(view.get('controller.recommendations').findProperty('name', 
'dependent2').parentConfigs.toArray()).to.be.eql(["config2"]);
+      expect(view.get('controller.recommendations.length')).to.be.eql(2);
     });
 
     it('dependent config value should be set with inital or saved when it has 
one parent', function() {
@@ -237,7 +237,7 @@ describe('App.ConfigWidgetView', function () {
           ])
         })
       ]);
-      view.set('controller._dependentConfigValues', [
+      view.set('controller.recommendations', [
         {propertyName: 'dependent1', parentConfigs: ['config1', 'config2'], 
fileName: 'some-file' },
         {propertyName: 'dependent2', parentConfigs: ['config2', 'config1'], 
fileName: 'some-file'},
         {propertyName: 'dependent3', parentConfigs: ['config1'], fileName: 
'some-file' }

Reply via email to