Repository: ambari
Updated Branches:
  refs/heads/trunk fb763311e -> 9f87c98dc


AMBARI-10230 Support config-dependency changes when they cross services. 
(ababiichuk)


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

Branch: refs/heads/trunk
Commit: 9f87c98dcf352f2bae671556e74e06798ee0a5a6
Parents: fb76331
Author: aBabiichuk <ababiic...@cybervisiontech.com>
Authored: Fri Mar 27 12:31:25 2015 +0200
Committer: aBabiichuk <ababiic...@cybervisiontech.com>
Committed: Fri Mar 27 12:31:25 2015 +0200

----------------------------------------------------------------------
 .../controllers/main/service/info/configs.js    | 338 +++++------
 ambari-web/app/messages.js                      |   3 +
 .../mixins/common/configs/enhanced_configs.js   | 586 ++++++++++++++++---
 ambari-web/app/mixins/common/serverValidator.js |  77 ---
 .../modal_popups/dependent_configs_list.hbs     |   8 +-
 .../common/modal_popups/select_groups_popup.hbs |  32 +
 ambari-web/app/views.js                         |   1 +
 .../dependent_configs_list_popup.js             |  12 +-
 .../common/modal_popups/select_groups_popup.js  |  77 +++
 .../main/service/info/config_test.js            |  43 --
 .../common/configs/enhanced_configs_test.js     |  19 +-
 11 files changed, 764 insertions(+), 432 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/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 b126798..19179a0 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -38,6 +38,10 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
   requestInProgress: null,
   selectedServiceConfigTypes: [],
   selectedServiceSupportsFinal: [],
+
+  /**
+   * config groups for current service
+   */
   configGroups: [],
   allConfigs: [],
   uiConfigs: [],
@@ -65,19 +69,6 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
   }.property('selectedVersion', 'content.serviceName', 'dataIsLoaded'),
 
   /**
-   * array that contains config properties that were changed and
-   * belongs to not current service
-   * @returns {*|Array}
-   */
-  unsavedDependentConfigs: function() {
-    return App.ConfigProperty.find().filter(function(cp) {
-      return cp.get('stackConfigProperty.serviceName') !== 
this.get('content.serviceName')
-        && this.get('dependentFileNames').contains(cp.get('fileName'))
-        && cp.get('isNotDefaultValue');
-    }, this);
-  },
-
-  /**
    * @type {boolean}
    */
   canEdit: function () {
@@ -252,8 +243,6 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
    */
   isInit: true,
 
-  restartHosts: Em.A(),
-
   /**
    * On load function
    */
@@ -261,10 +250,12 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
     console.log("TRACE: Loading configure for service");
     var self = this;
     if (App.get('supports.enhancedConfigs')) {
-      
App.config.loadConfigTheme(this.get('content.serviceName')).then(function() {
-        self.loadDependentConfigs().done(function () {
-          
App.themesMapper.generateAdvancedTabs([self.get('content.serviceName')]);
-        });
+      
App.config.loadConfigTheme(this.get('content.serviceName')).always(function() {
+        self.setDependentServices(self.get('content.serviceName'));
+        
App.themesMapper.generateAdvancedTabs([self.get('content.serviceName')]);
+        if (self.get('dependentServiceNames.length') > 0) {
+          
App.config.loadConfigCurrentVersions(self.get('dependentServiceNames'));
+        }
       });
     }
     this.clearStep();
@@ -333,73 +324,6 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
   },
 
   /**
-   * this method defines dependent file names for configs
-   * and load them to model
-   * @method loadDependentConfigs
-   */
-  loadDependentConfigs: function() {
-    /**
-     * filter out configs for current service with
-     * <code>propertyDependedBy<code>
-     * @type {Array}
-     */
-    var serviceStackProperties = 
App.StackConfigProperty.find().filter(function(stackProperty) {
-      return stackProperty.get('serviceName') === 
this.get('content.serviceName') && 
stackProperty.get('propertyDependedBy.length') > 0
-    }, this);
-
-    /**
-     * defines what fileNames should UI load
-     */
-    serviceStackProperties.forEach(function(serviceStackProperty) {
-      this.calculateDependentFileNames(serviceStackProperty);
-    }, this);
-
-    var serviceConfigsToLoad = this.getServiceNamesForConfigs();
-
-    /**
-     * load serviceConfigVersion
-     * by serviceName that has dependent properties
-     */
-    if (serviceConfigsToLoad.length > 0) {
-      return App.config.loadConfigCurrentVersions(serviceConfigsToLoad);
-    }
-  },
-
-  /**
-   * get required fileNames that has dependencies
-   * @returns {string[]}
-   */
-  getServiceNamesForConfigs: function() {
-    return App.StackService.find().filter(function(s) {
-      for (var i = 0; i < this.get('dependentFileNames.length'); i++) {
-        if 
(Object.keys(s.get('configTypes')).contains(App.config.getConfigTagFromFileName(this.get('dependentFileNames')[i])))
-          return true;
-      }
-      return false;
-    }, 
this).mapProperty('serviceName').concat(this.get('content.serviceName'));
-  },
-
-  /**
-   * dependent file names for configs
-   */
-  dependentFileNames: [],
-
-  /**
-   * defines file names for configs
-   * @param {App.StackConfigProperty} stackProperty
-   */
-  calculateDependentFileNames: function(stackProperty) {
-    if (stackProperty.get('propertyDependedBy.length') > 0) {
-      stackProperty.get('propertyDependedBy').forEach(function(dependent) {
-        if (!this.get('dependentFileNames').contains(dependent.type)) {
-          this.get('dependentFileNames').push(dependent.type);
-        }
-        
this.calculateDependentFileNames(App.StackConfigProperty.find(dependent.name + 
"_" + dependent.type));
-      }, this);
-    }
-  },
-
-  /**
    * get service config versions of current service
    */
   loadServiceConfigVersions: function () {
@@ -526,6 +450,7 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
 
   /**
    * load config groups of service
+   * and dependent services
    */
   loadServiceTagsAndGroups: function () {
     this.trackRequest(App.ajax.send({
@@ -533,7 +458,7 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
       sender: this,
       data: {
         serviceName: this.get('content.serviceName'),
-        urlParams: "&config_groups/ConfigGroup/tag=" + 
this.get('content.serviceName')
+        urlParams: "&config_groups/ConfigGroup/tag.in(" + 
[this.get('content.serviceName')].concat(this.get('dependentServiceNames')).join(',')+
 ')'
       },
       success: 'loadServiceConfigsSuccess'
     }));
@@ -543,20 +468,6 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
     this.setConfigGroups(data, opt, params);
   },
 
-  setConfigTags: function (data, opt, params) {
-    var serviceConfigsDef = 
this.get('serviceConfigs').findProperty('serviceName', 
this.get('content.serviceName'));
-    var siteToTagMap = {};
-    var configTypesRendered = 
Object.keys(serviceConfigsDef.get('configTypesRendered'));
-    configTypesRendered.forEach(function (siteName) {
-      if (data.Clusters.desired_configs[siteName]) {
-        siteToTagMap[siteName] = data.Clusters.desired_configs[siteName].tag;
-      } else {
-        siteToTagMap[siteName] = 'version1';
-      }
-    }, this);
-    this.loadedClusterSiteToTagMap = siteToTagMap;
-  },
-
   setConfigGroups: function (data, opt, params) {
     var serviceName = this.get('content.serviceName');
     var displayName = this.get('content.displayName');
@@ -594,9 +505,50 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
             selectedConfigGroup = newConfigGroup;
           }
           configGroups.push(newConfigGroup);
+        } else if (this.get('dependentServiceNames').contains(item.tag)) {
+          /**
+           * Load config groups for services that has dependent properties.
+           * If user change properties that have dependencies in not default 
config group
+           * user should pick to which config group Ambari should save these 
properties
+           * @type {App.ConfigGroup}
+           */
+          var newDependentConfigGroup = App.ConfigGroup.create({
+            id: item.id,
+            name: item.group_name,
+            description: item.description,
+            isDefault: false,
+            parentConfigGroup: null,
+            service: App.Service.find().findProperty('serviceName', item.tag),
+            hosts: item.hosts.mapProperty('host_name')
+          });
+          if (!this.get('dependentConfigGroups').findProperty('name', 
item.group_name)) {
+            this.get('dependentConfigGroups').push(newDependentConfigGroup);
+          }
         }
       }, this);
     }
+    this.get('dependentServiceNames').forEach(function(serviceName) {
+      if (serviceName !== this.get('content.serviceName')) {
+        var service = App.Service.find().findProperty('serviceName', 
serviceName);
+        /**
+         * default groups for dependent services
+         * @type {App.ConfigGroup}
+         */
+        var defaultConfigGroup = App.ConfigGroup.create({
+          name: service.get('displayName') + " Default",
+          description: "Default cluster level " + serviceName + " 
configuration",
+          isDefault: true,
+          hosts: [],
+          parentConfigGroup: null,
+          service: service,
+          serviceName: serviceName,
+          configSiteTags: []
+        });
+        if (!this.get('dependentConfigGroups').findProperty('name', 
defaultConfigGroup.get('name'))) {
+          this.get('dependentConfigGroups').push(defaultConfigGroup);
+        }
+      }
+    }, this);
     this.set('configGroups', configGroups);
     var defaultConfigGroup = App.ConfigGroup.create({
       name: displayName + " Default",
@@ -1202,7 +1154,6 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
     }
     return newSCP;
   },
-
   /**
    * tells controller in saving configs was started
    * for now just changes flag <code>saveInProgress<code> to true
@@ -1237,27 +1188,11 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
   showWarningPopupsBeforeSave: function() {
     var displayName = this.get('content.displayName');
     if (this.isDirChanged()) {
-      App.showConfirmationPopup(this.showDependenciesAndSave.bind(this),
+      App.showConfirmationPopup(this.restartServicePopup.bind(this),
         
Em.I18n.t('services.service.config.confirmDirectoryChange').format(displayName),
         this.completeSave.bind(this)
       );
     } else {
-      this.showDependenciesAndSave();
-    }
-  },
-
-  /**
-   * if there are some dependent configs in different services
-   * this popup will be shown with info about this configs
-   * @method showDependenciesAndSave
-   */
-  showDependenciesAndSave: function() {
-    var dependentConfigs = this.unsavedDependentConfigs();
-    if (dependentConfigs.length > 0) {
-      App.showDependentConfigsPopup(dependentConfigs,
-        this.restartServicePopup.bind(this),
-        this.completeSave.bind(this));
-    } else {
       this.restartServicePopup();
     }
   },
@@ -1303,51 +1238,39 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
         configs = App.config.textareaIntoFileConfigs(configs, 
'capacity-scheduler.xml');
       }
 
-      if (App.get('supports.enhancedConfigs')) {
-        if (this.get('content.serviceName') === 'HIVE') {
-          this.setHiveHostName(configs);
-        } else if (this.get('content.serviceName') === 'OOZIE') {
-          this.setOozieHostName(configs);
-        }
-
-        this.loadConfigsToModel(configs, self.get('selectedVersion'));
+      /**
+       * generates list of properties that was changed
+       * @type {Array}
+       */
+      var modifiedConfigs = configs
+        // get only modified and created configs
+        .filter(function (config) {
+          return config.get('isNotDefaultValue') || config.get('isNotSaved');
+        })
+        // get file names and add file names that was modified, for example 
after property removing
+        .mapProperty('filename').concat(this.get('modifiedFileNames')).uniq()
+        // get configs by filename
+        .map(function (fileName) {
+          return configs.filterProperty('filename', fileName);
+        });
 
-        this.saveEnhancedConfigs();
+      if (!!modifiedConfigs.length) {
+        // concatenate results
+        modifiedConfigs = modifiedConfigs.reduce(function (current, prev) {
+          return current.concat(prev);
+        });
+      }
+      // save modified original configs that have no group
+      this.saveSiteConfigs(modifiedConfigs.filter(function (config) {
+        return !config.get('group');
+      }));
 
-      } else {
-        /**
-         * generates list of properties that was changed
-         * @type {Array}
-         */
-        var modifiedConfigs = configs
-          // get only modified and created configs
-          .filter(function (config) {
-            return config.get('isNotDefaultValue') || config.get('isNotSaved');
-          })
-          // get file names and add file names that was modified, for example 
after property removing
-          .mapProperty('filename').concat(this.get('modifiedFileNames')).uniq()
-          // get configs by filename
-          .map(function (fileName) {
-            return configs.filterProperty('filename', fileName);
-          });
+      /**
+       * First we put cluster configurations, which automatically creates 
/configurations
+       * resources. Next we update host level overrides.
+       */
+      this.doPUTClusterConfigurations();
 
-        if (!!modifiedConfigs.length) {
-          // concatenate results
-          modifiedConfigs = modifiedConfigs.reduce(function (current, prev) {
-            return current.concat(prev);
-          });
-        }
-        // save modified original configs that have no group
-        this.saveSiteConfigs(modifiedConfigs.filter(function (config) {
-          return !config.get('group');
-        }));
-
-        /**
-         * First we put cluster configurations, which automatically creates 
/configurations
-         * resources. Next we update host level overrides.
-         */
-        this.doPUTClusterConfigurations();
-      }
     } else {
       var overridenConfigs = [];
       var groupHosts = [];
@@ -1356,33 +1279,33 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
       });
       // find custom original properties that assigned to selected config group
       overridenConfigs = 
overridenConfigs.concat(configs.filterProperty('group')
-        .filter(function(config) { return config.get('group.name') == 
self.get('selectedConfigGroup.name'); }));
-
-      if (App.get('supports.enhancedConfigs')) {
-
-        this.loadConfigsToModel(overridenConfigs, this.get('selectedVersion'));
-
-        this.saveEnhancedConfigsAndGroup(this.get('selectedConfigGroup'));
+        .filter(function (config) {
+          return config.get('group.name') == 
self.get('selectedConfigGroup.name');
+        }));
 
-      } else {
-        this.formatConfigValues(overridenConfigs);
-        selectedConfigGroup.get('hosts').forEach(function (hostName) {
-          groupHosts.push({"host_name": hostName});
-        });
+      this.formatConfigValues(overridenConfigs);
+      selectedConfigGroup.get('hosts').forEach(function (hostName) {
+        groupHosts.push({"host_name": hostName});
+      });
 
-        this.putConfigGroupChanges({
-          ConfigGroup: {
-            "id": selectedConfigGroup.get('id'),
-            "cluster_name": App.get('clusterName'),
-            "group_name": selectedConfigGroup.get('name'),
-            "tag": selectedConfigGroup.get('service.id'),
-            "description": selectedConfigGroup.get('description'),
-            "hosts": groupHosts,
-            "service_config_version_note": 
this.get('serviceConfigVersionNote'),
-            "desired_configs": this.buildGroupDesiredConfigs(overridenConfigs)
-          }
-        }, true);
-      }
+      /**
+       * if there are some changes in dependent configs
+       * need to save these config to in separate request
+       */
+      this.saveDependentGroups();
+
+      this.putConfigGroupChanges({
+        ConfigGroup: {
+          "id": selectedConfigGroup.get('id'),
+          "cluster_name": App.get('clusterName'),
+          "group_name": selectedConfigGroup.get('name'),
+          "tag": selectedConfigGroup.get('service.id'),
+          "description": selectedConfigGroup.get('description'),
+          "hosts": groupHosts,
+          "service_config_version_note": this.get('serviceConfigVersionNote'),
+          "desired_configs": this.buildGroupDesiredConfigs(overridenConfigs)
+        }
+      }, true);
     }
   },
 
@@ -1658,7 +1581,7 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
     if (showPopup) {
       ajaxOptions.success = "putConfigGroupChangesSuccess";
     }
-    App.ajax.send(ajaxOptions);
+    return App.ajax.send(ajaxOptions);
   },
 
   putConfigGroupChangesSuccess: function () {
@@ -2021,7 +1944,9 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
      * adding config tags for dependentConfigs
      */
     for (var i = 0; i < this.get('dependentFileNames.length'); i++) {
-      serviceConfigTags.pushObject({siteName: 
this.get('dependentFileNames')[i]});
+      if (!serviceConfigTags.findProperty('siteName', 
this.get('dependentFileNames')[i])) {
+        serviceConfigTags.pushObject({siteName: 
this.get('dependentFileNames')[i]});
+      }
     }
     this.setNewTagNames(serviceConfigTags);
     var siteNameToServerDataMap = {};
@@ -2035,7 +1960,29 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
     }, this);
     configsToSave = this.filterChangedConfiguration(configsToSave);
     if (configsToSave.length > 0) {
-      this.doPUTClusterConfigurationSites(configsToSave);
+      var data = [];
+      data.pushObject(JSON.stringify({
+        Clusters: {
+          desired_config: configsToSave
+        }
+      }));
+      if (App.get('supports.enhancedConfigs')) {
+        /**
+         * adding configs that were changed for dependent services
+         * if there are such configs
+         */
+        this.get('dependentServiceNames').forEach(function(serviceName) {
+          var dependentConfigsToSave = 
this.getDependentConfigObject(serviceName);
+          if (dependentConfigsToSave.length > 0) {
+            data.pushObject(JSON.stringify({
+              Clusters: {
+                desired_config: dependentConfigsToSave
+              }
+            }));
+          }
+        }, this);
+      }
+      this.doPUTClusterConfigurationSites(data);
     } else {
       this.onDoPUTClusterConfigurations();
     }
@@ -2183,15 +2130,15 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
   /**
    * Saves configuration of set of sites. The provided data
    * contains the site name and tag to be used.
-   * @param {Object} sites
+   * @param {Object[]} services
    * @method doPUTClusterConfigurationSites
    */
-  doPUTClusterConfigurationSites: function (sites) {
+  doPUTClusterConfigurationSites: function (services) {
     App.ajax.send({
-      name: 'common.service.configurations',
+      name: 'common.across.services.configurations',
       sender: this,
       data: {
-        desired_config: sites
+        data: '[' + services.toString() + ']'
       },
       success: 'doPUTClusterConfigurationSiteSuccessCallback',
       error: 'doPUTClusterConfigurationSiteErrorCallback'
@@ -2640,9 +2587,10 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
    * add new overridden property to config property object
    * @param {object} serviceConfigProperty - config property object
    * @param {App.ConfigGroup} group - config group for new property
+   * @param {String} value
    * @method addOverrideProperty
    */
-  addOverrideProperty: function (serviceConfigProperty, group) {
+  addOverrideProperty: function (serviceConfigProperty, group, value) {
     var overrides = serviceConfigProperty.get('overrides');
     if (!overrides) {
       overrides = [];
@@ -2650,7 +2598,7 @@ App.MainServiceInfoConfigsController = 
Em.Controller.extend(App.ServerValidatorM
     }
     // create new override with new value
     var newSCP = App.ServiceConfigProperty.create(serviceConfigProperty);
-    newSCP.set('value', '');
+    newSCP.set('value', value || '');
     newSCP.set('isOriginalSCP', false); // indicated this is overridden value,
     newSCP.set('parentSCP', serviceConfigProperty);
     newSCP.set('isEditable', true);

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 50d62f0..42a0aaa 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -255,6 +255,7 @@ Em.I18n.translations = {
   'common.minutes': "Minutes",
   'common.seconds': "Seconds",
   'common.milliseconds': "Milliseconds",
+  'common.configGroup': 'Config Group',
 
   'models.alert_instance.tiggered.verbose': "Occured on {0} <br> Checked on 
{1}",
   'models.alert_definition.triggered.verbose': "Occured on {0}",
@@ -344,6 +345,8 @@ Em.I18n.translations = {
   'popup.dependent.configs.table.currentValue': 'Current value',
   'popup.dependent.configs.table.recommendedValue': 'Recommended value',
 
+  'popup.dependent.configs.select.config.group': 'Please select to which 
config group would you like to save dependent properties',
+
   'login.header':'Sign in',
   'login.username':'Username',
   'login.loginButton':'Sign in',

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/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 a661ddb..61c2a2e 100644
--- a/ambari-web/app/mixins/common/configs/enhanced_configs.js
+++ b/ambari-web/app/mixins/common/configs/enhanced_configs.js
@@ -17,127 +17,131 @@
  */
 
 var App = require('app');
+var blueprintUtils = require('utils/blueprint');
 
 App.EnhancedConfigsMixin = Em.Mixin.create({
 
-  modifiedFileNames: [],
-
   /**
-   * merge step configs from model
-   * for default config group properties should be list
-   * of changed properties
-   * @param properties
-   * @param currentVersionNumber
+   * values for dependent configs
+   * @type {Object[]}
+   * ex:
+   * {
+   *   saveRecommended: {boolean}, //by default is true (checkbox binding)
+   *   fileName: {string}, //file name without '.xml'
+   *   propertyName: {string},
+   *   configGroup: {string},
+   *   value: {string},
+   *   serviceName: {string},
+   *   recommendedValue: {string}
+   * }
+   * @private
    */
-  loadConfigsToModel: function(properties, currentVersionNumber) {
-    var serviceName = this.get('content.serviceName');
-    if (properties && properties.length) {
-      properties.forEach(function(p) {
-        var configFromModel = App.ConfigProperty.find(p.get('name') + '_' + 
App.config.getConfigTagFromFileName(p.get('filename')) + '_' + 
currentVersionNumber);
-        if (configFromModel && configFromModel.get('name')) {
-          configFromModel.setProperties({
-            'value': p.get('value'),
-            'isFinal': p.get('isFinal'),
-            'defaultValue': p.get('defaultValue'),
-            'defaultIsFinal': p.get('defaultIsFinal'),
-            'isRequiredByAgent': p.get('isRequiredByAgent'),
-            'isNotSaved': p.get('isNotSaved')
-          });
-        } else {
-          App.store.load(App.ConfigProperty, {
-            id: p.get('name') + '_' + 
App.config.getConfigTagFromFileName(p.get('filename')) + '_' + 
currentVersionNumber,
-            name: p.get('name'),
-            file_name: p.get('filename'),
-            value: p.get('value'),
-            is_final: p.get('isFinal'),
-            default_value: p.get('defaultValue'),
-            default_is_final: p.get('defaultIsFinal'),
-            is_required_by_agent: p.get('isRequiredByAgent'),
-            is_not_saved: p.get('isNotSaved'),
-            is_required: false,
-            config_version_id: serviceName + '_' + currentVersionNumber
-          })
-        }
-      });
-    }
-  },
+  _dependentConfigValues: [],
 
   /**
-   * generates data and save configs for default group
-   * @method saveEnhancedConfigs
+   * dependent file names for configs
+   * @type {string[]}
    */
-  saveEnhancedConfigs: function() {
+  dependentFileNames: [],
 
-    var fileNamesToSave = 
this.getFileNamesToSave(this.get('modifiedFileNames'));
+  /**
+   * dependent service names for configs
+   * @type {string[]}
+   */
+  dependentServiceNames: [],
 
-    var configsToSave = this.getConfigsToSave(fileNamesToSave);
+  /**
+   * config groups for dependent services
+   * @type {App.ConfigGroup[]}
+   */
+  dependentConfigGroups: [],
 
-    var desired_configs = this.generateDesiredConfigsJSON(configsToSave, 
fileNamesToSave, this.get('serviceConfigNote'));
+  /**
+   * contains config group name that need to be saved
+   * {
+   *    serviceName: configGroupName
+   * }
+   * @type {Object}
+   */
+  groupsToSave: {},
 
-    this.doPUTClusterConfigurationSites(desired_configs);
-  },
+  /***********************************METHODS THAT WORKS WITH MODEL 
********************************************/
 
   /**
-   * generates data and save configs for not default group
-   * @param selectedConfigGroup
-   * @method saveEnhancedConfigsAndGroup
+   * generates desired_config objects for default config group
+   * @returns {Object}
+   * @method getDependentConfigObject
    */
-  saveEnhancedConfigsAndGroup: function(selectedConfigGroup) {
-    //TODO update for dependent configs
-    var serviceConfigVersion = 
App.ConfigVersion.find().findProperty('groupName', 
selectedConfigGroup.get('name'));
+  getDependentConfigObject: function(serviceName) {
 
-    var overridenConfigs = App.ConfigProperty.find().filter(function(cp) {
-      return cp.get('configVersion.groupId') === selectedConfigGroup.get('id') 
|| cp.get('isNotDefaultValue');
-    });
+    var fileNamesToSave = this._getFileNamesToSave(serviceName);
 
-    var hostNames = serviceConfigVersion.get('hosts').map(function(hostName) {
-      return  {
-        "host_name": hostName
-      }
-    });
+    var configsToSave = this._getConfigsToSave(fileNamesToSave);
 
-    var fileNamesToSave = overridenConfigs.mapProperty('fileName').uniq();
-
-    this.putConfigGroupChanges({
-      ConfigGroup: {
-        "id": selectedConfigGroup.get('id'),
-        "cluster_name": App.get('clusterName'),
-        "group_name": selectedConfigGroup.get('name'),
-        "tag": selectedConfigGroup.get('service.id'),
-        "description": selectedConfigGroup.get('description'),
-        "hosts": hostNames,
-        "service_config_version_note": this.get('serviceConfigNote'),
-        "desired_configs": this.generateDesiredConfigsJSON(overridenConfigs, 
fileNamesToSave, null, true)
-      }
-    }, true);
+    return this.generateDesiredConfigsJSON(configsToSave, fileNamesToSave, 
this.get('serviceConfigNote'));
   },
 
   /**
-   * get file names that need to be saved
-   * @param {Array} modifiedFileNames
-   * @returns {Ember.Enumerable}
+   * generates data and save configs for not default groups only
+   * that uses configs from model App.ConfigProperty
+   * @param serviceName
+   * @param configGroup
+   * @method saveEnhancedConfigsAndGroup
    */
-  getFileNamesToSave: function(modifiedFileNames) {
-    return App.ConfigProperty.find().filter(function(cp) {
-      return cp.get('isNotDefaultValue') || cp.get('isNotSaved');
-    }, this).mapProperty('fileName').concat(modifiedFileNames).uniq();
+  saveModelConfigsWithGroup: function(serviceName, configGroup) {
+    /**
+     * for now we are saving configs from model only for dependent services
+     * so excluding situation in current service is trying to be saved
+     * this is temporary solution
+     */
+    if (this.get('content.serviceName') !== serviceName) {
+
+      var configsToSave = App.ConfigProperty.find().filter(function(cp) {
+        return cp.get('configVersion.groupName') == configGroup.get('name') || 
cp.get('isNotSaved');
+      });
+      if (configsToSave.length > 0) {
+        var hostNames = configGroup.get('hosts').map(function(hostName) {
+          return  {
+            "host_name": hostName
+          }
+        });
+
+        var fileNamesToSave = configsToSave.mapProperty('fileName').uniq();
+
+        this.putConfigGroupChanges({
+          ConfigGroup: {
+            "id": configGroup.get('id'),
+            "cluster_name": App.get('clusterName'),
+            "group_name": configGroup.get('name'),
+            "tag": configGroup.get('service.id'),
+            "description": configGroup.get('description'),
+            "hosts": hostNames,
+            "service_config_version_note": this.get('serviceConfigNote'),
+            "desired_configs": this.generateDesiredConfigsJSON(configsToSave, 
fileNamesToSave, null, true)
+          }
+        })
+      }
+    }
   },
 
   /**
-   * get configs that need to be saved, for default group
-   * @param fileNamesToSave
-   * @returns {App.ConfigProperty[]}
+   * save configs from model to default config group
+   * @param serviceName
    */
-  getConfigsToSave: function(fileNamesToSave) {
-    if (Em.isArray(fileNamesToSave) && fileNamesToSave.length) {
-      return App.ConfigProperty.find().filter(function(cp) {
-        return (fileNamesToSave.contains(cp.get('fileName')) && 
cp.get('isOriginalSCP')) || cp.get('isNotSaved');
-      });
-    } else {
-      return Em.A([]);
+  saveModelConfigs: function(serviceName) {
+    var desired_configs = this.getDependentConfigObject(serviceName);
+    if (desired_configs.length > 0) {
+      var data = [JSON.stringify({
+        Clusters: {
+          desired_config: desired_configs
+        }
+      })];
+      this.doPUTClusterConfigurationSites(data);
     }
   },
 
+  /********************************METHODS THAT GENERATES JSON TO SAVE 
*****************************************/
+
   /**
    * generating common JSON object for desired configs
    * @param configsToSave
@@ -250,13 +254,403 @@ App.EnhancedConfigsMixin = Em.Mixin.create({
     }
   },
 
+  /******************************METHODS THAT WORKS WITH DEPENDENT CONFIGS 
*************************************/
+
+  /**
+   * clear values for dependent configs
+   * @method clearDependentConfigs
+   * @private
+   */
+  clearDependentConfigs: function() {
+    this.set('groupsToSave', {});
+    this.set('_dependentConfigValues', []);
+  },
+
+  onConfigGroupChangeForEnhanced: function() {
+    this.clearDependentConfigs();
+  }.observes('selectedConfigGroup'),
+
+
+  /**
+   * saves properties for dependent service to config group based on 
<code>groupsToSave<code>
+   */
+  saveDependentGroups: function() {
+    if (App.get('supports.enhancedConfigs') && 
this.get('dependentServiceNames.length') && 
Object.keys(this.get('groupsToSave')).length > 0) {
+
+      this.get('dependentServiceNames').forEach(function(serviceName) {
+        if (this.get('groupsToSave')[serviceName]) {
+          if (this.get('groupsToSave')[serviceName].contains('Default')) {
+            this.saveModelConfigs(serviceName);
+          } else {
+            this.saveModelConfigsWithGroup(serviceName, 
this.get('dependentConfigGroups').findProperty('name', 
this.get('groupsToSave')[serviceName]));
+          }
+        }
+      }, this);
+
+    }
+  },
+
+
+  /**
+   * runs <code>setDependentServicesAndFileNames<code>
+   * for stack properties for current service
+   * @method loadDependentConfigs
+   */
+  setDependentServices: function(serviceName) {
+    App.StackConfigProperty.find().forEach(function(stackProperty) {
+      if (stackProperty.get('serviceName') === serviceName && 
stackProperty.get('propertyDependedBy.length') > 0) {
+        this._setDependentServicesAndFileNames(stackProperty);
+      }
+    }, this);
+  },
+
   /**
-   * overriden in controller
+   * get service for current config type
+   * @param {String} configType - config fileName without xml
+   * @return App.StackService
    */
-  doPUTClusterConfigurationSites: Em.K,
+  getServiceByConfigType: function(configType) {
+    return App.StackService.find().find(function(s) {
+      return Object.keys(s.get('configTypes')).contains(configType);
+    });
+  },
+
+  /**
+   * show popup to select config group for dependent services
+   * to which dependent configs will ve saved
+   * @method showSelectGroupsPopup
+   */
+  showSelectGroupsPopup: function(callback) {
+    var servicesWithConfigGroups = [];
+    this.get('dependentServiceNames').forEach(function(serviceName) {
+      if (serviceName !== this.get('content.serviceName')) {
+        if (!this.get('groupsToSave')[serviceName]) {
+          var groups = 
this.get('dependentConfigGroups').filterProperty('service.serviceName', 
serviceName).mapProperty('name').uniq();
+          servicesWithConfigGroups.push({
+            serviceName: serviceName,
+            configGroupNames: groups
+          })
+        }
+      }
+    }, this);
+    if (servicesWithConfigGroups.length > 0) {
+      App.showSelectGroupsPopup(servicesWithConfigGroups, 
this.get('groupsToSave'), callback);
+    } else {
+      callback();
+    }
+  },
+
+
+  /**
+   * sends request to get values for dependent configs
+   * @param changedConfigs
+   * @returns {$.ajax|null}
+   */
+  getRecommendationsForDependencies: function(changedConfigs) {
+    if (Em.isArray(changedConfigs) && changedConfigs.length > 0) {
+      var recommendations = this.get('hostGroups');
+      var configs = this._getConfigsByGroup(this.get('stepConfigs'));
+      recommendations.blueprint.configurations = 
blueprintUtils.buildConfigsJSON(this.get('services'), configs);
+
+      var dataToSend = {
+        recommend: 'configurations',
+        hosts: this.get('hostNames'),
+        services: this.get('serviceNames'),
+        recommendations: recommendations
+      };
+      /** TODO uncomment when be will be ready
+       if (App.get('supports.enhancedConfigs')) {
+        dataToSend.recommend = 'configuration-dependencies';
+        dataToSend.changed_configurations = changedConfigs;
+      }
+       **/
+      return App.ajax.send({
+        name: 'config.recommendations',
+        sender: this,
+        data: {
+          stackVersionUrl: App.get('stackVersionURL'),
+          dataToSend: dataToSend
+        },
+        success: 'dependenciesSuccess',
+        error: 'dependenciesError'
+      });
+    } else {
+      return null;
+    }
+  },
 
   /**
-   * overriden in controller
+   * shows popup with results for recommended value
+   * if case properties that was changes belongs to not default group
+   * user should pick to what config group from dependent service dependent 
properties will be saved
+   * @param data
+   * @method dependenciesSuccess
    */
-  putConfigGroupChanges: Em.K
+  dependenciesSuccess: function (data) {
+    var self = this;
+    if (!this.get('selectedConfigGroup.isDefault')) {
+      self.showSelectGroupsPopup(function () {
+        self._saveRecommendedValues(data);
+        if (self.get('_dependentConfigValues.length') > 0) {
+          App.showDependentConfigsPopup(self.get('_dependentConfigValues'), 
function () {
+            self._saveDependentConfigs();
+          });
+        }
+      });
+    } else {
+      self._saveRecommendedValues(data);
+      if (self.get('_dependentConfigValues.length') > 0) {
+        App.showDependentConfigsPopup(self.get('_dependentConfigValues'), 
function () {
+          self._saveDependentConfigs();
+        });
+      }
+    }
+  },
+
+  /**
+   *
+   * @param jqXHR
+   * @param ajaxOptions
+   * @param error
+   * @param opt
+   */
+  dependenciesError: function(jqXHR, ajaxOptions, error, opt) {
+    App.ajax.defaultErrorHandler(jqXHR, opt.url, opt.method, jqXHR.status);
+  },
+
+
+  /**
+   * defines file names for configs and set them to 
<code>dependentFileNames<code> and
+   * defines service names for configs and set them to 
<code>dependentServiceNames<code>
+   * @param {App.StackConfigProperty} stackProperty
+   * @private
+   */
+  _setDependentServicesAndFileNames: function(stackProperty) {
+    if (stackProperty.get('propertyDependedBy.length') > 0) {
+      stackProperty.get('propertyDependedBy').forEach(function(dependent) {
+        var tag = App.config.getConfigTagFromFileName(dependent.type);
+        /** setting dependent fileNames (without '.xml') **/
+        if (!this.get('dependentFileNames').contains(tag)) {
+          this.get('dependentFileNames').push(tag);
+        }
+        /** setting dependent serviceNames (without current serviceName) **/
+        var dependentProperty = App.StackConfigProperty.find(dependent.name + 
"_" + tag);
+        if (dependentProperty) {
+          if 
(!this.get('dependentServiceNames').contains(dependentProperty.get('serviceName'))
 && dependentProperty.get('serviceName') !== this.get('content.serviceName')) {
+            
this.get('dependentServiceNames').push(dependentProperty.get('serviceName'));
+          }
+          this._setDependentServicesAndFileNames(dependentProperty);
+        }
+      }, this);
+    }
+  },
+
+  /**
+   * get file names that need to be saved
+   * used for default config group
+   * @param {String} serviceName
+   * @returns {Ember.Enumerable}
+   * @private
+   */
+  _getFileNamesToSave: function(serviceName) {
+    return App.ConfigProperty.find().filter(function(cp) {
+      return cp.get('isNotDefaultValue') && 
cp.get('stackConfigProperty.serviceName') === serviceName;
+    }, this).mapProperty('fileName').uniq();
+  },
+
+  /**
+   * get configs that need to be saved, for default group
+   * @param fileNamesToSave
+   * @returns {App.ConfigProperty[]}
+   * @private
+   */
+  _getConfigsToSave: function(fileNamesToSave) {
+    if (Em.isArray(fileNamesToSave) && fileNamesToSave.length) {
+      return App.ConfigProperty.find().filter(function(cp) {
+        return fileNamesToSave.contains(cp.get('fileName')) && 
cp.get('configVersion.isCurrent');
+      });
+    } else {
+      return Em.A([]);
+    }
+  },
+
+  /**
+   * save values that are stored in <code>_dependentConfigValues<code>
+   * for current service to step configs
+   * for dependent services to model
+   * @private
+   */
+  _saveDependentConfigs: function() {
+    var self = this;
+    this.get('_dependentConfigValues').forEach(function(dependentConfig) {
+      if (Em.get(dependentConfig, 'saveRecommended')) { // if saveRecommended 
is false leave properties as is
+        if (Em.get(dependentConfig, 'serviceName') === 
self.get('content.serviceName')) { //for current service save dependent 
properties to step configs
+          
self.get('stepConfigs').objectAt(0).get('configs').forEach(function(stepConfig) 
{
+            if (stepConfig.get('filename') === 
App.config.getOriginalFileName(Em.get(dependentConfig, 'fileName'))
+              && stepConfig.get('name') === Em.get(dependentConfig, 
'propertyName')) {
+              if (self.get('selectedConfigGroup.isDefault')) {
+                stepConfig.set('value', Em.get(dependentConfig, 
'recommendedValue'))
+              } else {
+                if (!stepConfig.get('overrides')) {
+                  stepConfig.set('overrides', Em.A([]));
+                }
+                var overridenConfig = 
stepConfig.get('overrides').findProperty('isEditable');
+                if (overridenConfig) {
+                  overridenConfig.set('value', Em.get(dependentConfig, 
'recommendedValue'));
+                } else {
+                  self.addOverrideProperty(stepConfig, 
self.get('selectedConfigGroup'), Em.get(dependentConfig, 'recommendedValue'));
+                }
+              }
+            }
+          })
+        } else { //for not current service save dependent properties to model
+
+          App.ConfigProperty.find().forEach(function(cp) {
+            if (cp.get('name') === Em.get(dependentConfig, 'propertyName')
+              && cp.get('fileName') === 
App.config.getOriginalFileName(Em.get(dependentConfig, 'fileName'))) {
+
+              if (self.get('selectedConfigGroup.isDefault') || 
Em.get(dependentConfig, 'configGroup').contains('Default')) {
+                if (cp.get('isOriginalSCP')) {
+                  cp.set('value', Em.get(dependentConfig, 'recommendedValue'))
+                }
+              } else {
+                if (cp.get('configVersion.groupName') === 
self.get('groupsToSave')[dependentConfig.serviceName]) {
+                  cp.set('value', Em.get(dependentConfig, 'recommendedValue'));
+                } else {
+                  App.store.load(App.ConfigProperty, {
+                    id: Em.get(dependentConfig, 'propertyName') + '_' + 
Em.get(dependentConfig, 'fileName') + '_',
+                    name: Em.get(dependentConfig, 'propertyName'),
+                    value: Em.get(dependentConfig, 'recommendedValue'),
+                    file_name: 
App.config.getOriginalFileName(Em.get(dependentConfig, 'fileName')),
+                    is_not_saved: true
+                  })
+                }
+              }
+
+            }
+          });
+        }
+      }
+    });
+  },
+
+  /**
+   * get array of config objects for current service depends on config group
+   * for default group - it will be current stepConfigs
+   * for not default group - overriden property in case there is such property 
in group
+   * otherwise - property from default group
+   * @param stepConfigs
+   * @returns {App.ServiceConfigProperty[]}
+   * @private
+   */
+  _getConfigsByGroup: function(stepConfigs) {
+    var configsToSend = [];
+    if (this.get('selectedConfigGroup.isDefault')) {
+      return stepConfigs;
+    } else {
+      stepConfigs.forEach(function(stepConfig) {
+        if (stepConfig.get('overrides')) {
+          var conf = stepConfig.get('overrides').findProperty('group.name', 
this.get('selectedConfigGroup.name'));
+          if (conf) {
+            configsToSend.pushObject(conf);
+          } else {
+            configsToSend.pushObject(stepConfig);
+          }
+        } else {
+          configsToSend.pushObject(stepConfig);
+        }
+      }, this)
+    }
+    return configsToSend;
+  },
+
+  /**
+   * saves values from response for dependent configs to 
<code>_dependentConfigValues<code>
+   * @param data
+   * @method saveRecommendedValues
+   * @private
+   */
+  _saveRecommendedValues: function(data) {
+    Em.assert('invalid data', data && data.resources[0] && 
Em.get(data.resources[0], 'recommendations.blueprint.configurations'));
+    var configs = data.resources[0].recommendations.blueprint.configurations;
+    for (var key in configs) {
+      for (var propertyName in configs[key].properties) {
+        var service = this.getServiceByConfigType(key);
+        var value = this._getCurrentValue(service.get('serviceName'), key, 
propertyName, this.get('selectedConfigGroup'));
+        if (!Em.isNone(value)) {
+          var dependentProperty = 
this.get('_dependentConfigValues').findProperty('propertyName', propertyName);
+          if (dependentProperty) {
+            if (value != configs[key].properties[propertyName]) {
+              Em.set(dependentProperty, 'value', value);
+              Em.set(dependentProperty, 'recommendedValue', 
configs[key].properties[propertyName]);
+            } else {
+              
this.get('_dependentConfigValues').removeObject(dependentProperty);
+            }
+          } else {
+            var configGroup = this.get('selectedConfigGroup.isDefault') ?
+              service.get('serviceName') + ' Default' : 
this.get('groupsToSave')[service.get('serviceName')] || 
this.get('selectedConfigGroup.name');
+            if (value != configs[key].properties[propertyName]) {
+              this.get('_dependentConfigValues').pushObject({
+                saveRecommended: true,
+                fileName: key,
+                propertyName: propertyName,
+                configGroup: configGroup,
+                value: value,
+                serviceName: service.get('serviceName'),
+                recommendedValue: configs[key].properties[propertyName]
+              });
+            }
+          }
+        }
+      }
+    }
+  },
+
+  /**
+   * get current value for property by serviceName, tag and ConfigGroup
+   * @param serviceName
+   * @param tag
+   * @param propertyName
+   * @param configGroup
+   * @returns {null|Object}
+   * @private
+   */
+  _getCurrentValue: function(serviceName, tag, propertyName, configGroup) {
+    if (serviceName == this.get('content.serviceName')) {
+      var stepConfig = 
this.get('stepConfigs').objectAt(0).get('configs').find(function(stepConfig) {
+        return (stepConfig.get('filename') === 
App.config.getOriginalFileName(tag) && stepConfig.get('name') === propertyName);
+      });
+      if (stepConfig) {
+        if (configGroup.get('isDefault') || 
Em.isNone(stepConfig.get('overrides'))) {
+          return stepConfig.get('value');
+        } else {
+          var overridenConfig = 
stepConfig.get('overrides').findProperty('isEditable');
+          if (overridenConfig) {
+            return overridenConfig.get('value');
+          } else {
+            return stepConfig.get('value');
+          }
+        }
+      }
+    } else {
+      var currentDefaultProperties = 
App.ConfigProperty.find().filter(function(cp) {
+        return cp.get('configVersion.isCurrent') && 
cp.get('configVersion.isDefault');
+      });
+      if (!this.get('selectedConfigGroup.isDefault') && 
(!this.get('groupsToSave')[serviceName] || 
!this.get('groupsToSave')[serviceName].contains('Default'))) {
+        var currentProperties = App.ConfigProperty.find().filter(function(cp) {
+          return cp.get('configVersion.isCurrent') && 
cp.get('configVersion.groupName') === this.get('groupsToSave')[serviceName];
+        }, this);
+        var modelConfig = currentProperties.findProperty('name', propertyName);
+        if (modelConfig) {
+          return modelConfig.get('value');
+        }
+      }
+
+      var modelDefaultConfig = currentDefaultProperties.findProperty('name', 
propertyName);
+      if (modelDefaultConfig) {
+        return modelDefaultConfig.get('value');
+      }
+    }
+    return null;
+  }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/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 4c89182..d6eeef3 100644
--- a/ambari-web/app/mixins/common/serverValidator.js
+++ b/ambari-web/app/mixins/common/serverValidator.js
@@ -135,83 +135,6 @@ App.ServerValidatorMixin = Em.Mixin.create({
   },
 
   /**
-   *
-   * @param changedConfigs
-   * @returns {$.ajax|null}
-   */
-  getRecommendationsForDependencies: function(changedConfigs) {
-    if (Em.isArray(changedConfigs) && changedConfigs.length > 0) {
-      var recommendations = this.get('hostGroups');
-      recommendations.blueprint.configurations = 
blueprintUtils.buildConfigsJSON(this.get('services'), this.get('stepConfigs'));
-
-      var dataToSend = {
-        recommend: 'configurations',
-        hosts: this.get('hostNames'),
-        services: this.get('serviceNames'),
-        recommendations: recommendations
-      };
-      /** TODO uncomment when be will be ready
-      if (App.get('supports.enhancedConfigs')) {
-        dataToSend.recommend = 'configuration-dependencies';
-        dataToSend.changed_configurations = changedConfigs;
-      }
-       **/
-    return App.ajax.send({
-        name: 'config.recommendations',
-        sender: this,
-        data: {
-          stackVersionUrl: App.get('stackVersionURL'),
-          dataToSend: dataToSend
-        },
-        success: 'dependenciesSuccess',
-        error: 'dependenciesError'
-      });
-    } else {
-      return null;
-    }
-  },
-
-  /**
-   *
-   * @param data
-   */
-  dependenciesSuccess: function(data) {
-    Em.assert('invalid data', data && data.resources[0] && 
Em.get(data.resources[0], 'recommendations.blueprint.configurations'));
-    var configs = data.resources[0].recommendations.blueprint.configurations;
-
-    this.loadConfigsToModel(this.get('stepConfigs')[0].get('configs'), 
this.get('selectedVersion'));
-
-    var currentProperties = 
App.ConfigProperty.find().filterProperty('configVersion.isCurrent').filterProperty('configVersion.groupId',
 -1);
-    for (var key in configs) {
-      for (var propertyName in configs[key].properties) {
-        var property = currentProperties.findProperty('name', propertyName)
-        if (property) {
-          property.set('recommendedValue', 
configs[key].properties[propertyName]);
-        }
-      }
-    }
-
-    var configsToShow = currentProperties.filter(function(p) {
-      return p.get('recommendedValue') && p.get('recommendedValue') !== 
p.get('value');
-    });
-
-    if (configsToShow.length > 0) {
-      App.showDependentConfigsPopup(configsToShow);
-    }
-  },
-
-  /**
-   *
-   * @param jqXHR
-   * @param ajaxOptions
-   * @param error
-   * @param opt
-   */
-  dependenciesError: function(jqXHR, ajaxOptions, error, opt) {
-    App.ajax.defaultErrorHandler(jqXHR, opt.url, opt.method, jqXHR.status);
-  },
-
-  /**
    * @method loadRecommendationsSuccess
    * success callback after loading recommendations
    * (used only during install)

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/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 926c5ea..3c02de9 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
@@ -25,8 +25,9 @@
     <tr>
       <th>{{t popup.dependent.configs.table.saveProperty}}</th>
       <th>{{t common.property}}</th>
-      <th>{{t common.fileName}}</th>
       <th>{{t common.service}}</th>
+      <th>{{t common.configGroup}}</th>
+      <th>{{t common.fileName}}</th>
       <th>{{t popup.dependent.configs.table.currentValue}}</th>
       <th>{{t popup.dependent.configs.table.recommendedValue}}</th>
     </tr>
@@ -35,9 +36,10 @@
     {{#each config in view.parentView.configs}}
       <tr>
         <td>{{view Em.Checkbox checkedBinding="config.saveRecommended"}}</td>
-        <td>{{config.name}}</td>
+        <td>{{config.propertyName}}</td>
+        <td>{{config.serviceName}}</td>
+        <td>{{config.configGroup}}</td>
         <td>{{config.fileName}}</td>
-        <td>{{config.stackConfigProperty.serviceName}}</td>
         <td>{{config.value}}</td>
         <td>{{config.recommendedValue}}</td>
       </tr>

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/ambari-web/app/templates/common/modal_popups/select_groups_popup.hbs
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/templates/common/modal_popups/select_groups_popup.hbs 
b/ambari-web/app/templates/common/modal_popups/select_groups_popup.hbs
new file mode 100644
index 0000000..09ee681
--- /dev/null
+++ b/ambari-web/app/templates/common/modal_popups/select_groups_popup.hbs
@@ -0,0 +1,32 @@
+{{!
+* 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.
+}}
+
+<div class="alert alert-warning">
+  {{t popup.dependent.configs.select.config.group}}
+</div>
+<form class="form-horizontal">
+{{#each service in view.parentView.dependentServices}}
+  <div class="form-group">
+    <label class="col-sm-2 control-label">{{service.serviceName}}&nbsp;</label>
+    <div class="col-sm-8">
+      {{view App.selectConfigGroupForService 
contentBinding="service.configGroupNames" 
serviceNameBinding="service.serviceName" groupsToSaveBinding="groupsToSave"}}
+    </div>
+  </div>
+{{/each}}
+</form>
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 8d099b1..b19b535 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -34,6 +34,7 @@ require('views/common/modal_popups/reload_popup');
 require('views/common/modal_popups/cluster_check_popup');
 require('views/common/modal_popups/invalid_KDC_popup');
 require('views/common/modal_popups/dependent_configs_list_popup');
+require('views/common/modal_popups/select_groups_popup');
 require('views/common/editable_list');
 require('views/common/rolling_restart_view');
 require('views/common/select_custom_date_view');

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js 
b/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js
index 73ed1f6..4c221ba 100644
--- a/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js
+++ b/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js
@@ -32,7 +32,7 @@ App.showDependentConfigsPopup = function (configs, callback, 
secondaryCallback)
     primary: Em.I18n.t('common.save'),
     secondary: Em.I18n.t('common.cancel'),
     header: Em.I18n.t('popup.dependent.configs.header'),
-    classNames: ['full-width-modal'],
+    classNames: ['sixty-percent-width-modal','modal-full-width'],
     configs: configs,
     bodyClass: Em.View.extend({
       templateName: 
require('templates/common/modal_popups/dependent_configs_list')
@@ -42,21 +42,13 @@ App.showDependentConfigsPopup = function (configs, 
callback, secondaryCallback)
     }.property('controller.stepConfigs.@each'),
     onPrimary: function () {
       this.hide();
-      configs.filterProperty('saveRecommended', true).forEach(function(c) {
-        c.set('value', c.get('recommendedValue'));
-        var stepConfig = this.get('stepConfigs').find(function(stepConf) {
-          return stepConf.get('name') === c.get('name') && 
stepConf.get('filename') === c.get('fileName');
-        });
-        if (stepConfig) {
-          stepConfig.set('value', c.get('recommendedValue'));
-        }
-      }, this);
       if (callback) {
         callback();
       }
     },
     onSecondary: function() {
       this.hide();
+      configs.setEach('saveRecommended', false);
       if(secondaryCallback) {
         secondaryCallback();
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/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
new file mode 100644
index 0000000..0448cdf
--- /dev/null
+++ b/ambari-web/app/views/common/modal_popups/select_groups_popup.js
@@ -0,0 +1,77 @@
+/**
+ * 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');
+
+/**
+ * Show confirmation popup
+ * @param {[Object]} servicesWithGroups
+ * @param {Object} groupsToSave
+ * @param {function} [callback=null]
+ * @param {function} [secondaryCallback=null]
+ * we use this parameter to defer saving configs before we make some decisions.
+ * @return {App.ModalPopup}
+ */
+App.showSelectGroupsPopup = function (servicesWithGroups, groupsToSave, 
callback, secondaryCallback) {
+  return App.ModalPopup.show({
+    encodeBody: false,
+    primary: Em.I18n.t('common.save'),
+    secondary: Em.I18n.t('common.cancel'),
+    header: Em.I18n.t('popup.dependent.configs.header'),
+    dependentServices: servicesWithGroups,
+    groupsToSave: groupsToSave,
+    bodyClass: Em.View.extend({
+      templateName: 
require('templates/common/modal_popups/select_groups_popup')
+    }),
+
+    onPrimary: function () {
+      this._super();
+      if (callback) {
+        callback();
+      }
+    },
+
+    onSecondary: function() {
+      this._super();
+      if(secondaryCallback) {
+        secondaryCallback();
+      }
+    }
+  });
+};
+
+App.selectConfigGroupForService = Ember.Select.extend({
+
+  /**
+   * set Default group by default
+   */
+  didInsertElement: function() {
+    var defaultVersion = this.get('content').find(function(cg) {
+      return cg.contains('Default');
+    });
+    this.set('value', defaultVersion);
+  },
+
+  /**
+   *
+   */
+  onChangeValue: function() {
+    var groupsToSave = this.get('groupsToSave');
+    groupsToSave[this.get('serviceName')] = this.get('value');
+  }.observes('value')
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/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 9de9f39..9614e3a 100644
--- a/ambari-web/test/controllers/main/service/info/config_test.js
+++ b/ambari-web/test/controllers/main/service/info/config_test.js
@@ -1315,47 +1315,4 @@ describe("App.MainServiceInfoConfigsController", 
function () {
     });
   });
 
-  describe('#calculateDependentFileNames()', function() {
-
-    beforeEach(function() {
-      mainServiceInfoConfigsController.set('dependentFileNames', []);
-      App.resetDsStoreTypeMap(App.StackConfigProperty);
-      App.StackConfigProperty.createRecord({id: 'name1_site1', 
propertyDependedBy: [{
-        type: 'site2',
-        name: 'name2'
-      }]});
-      App.StackConfigProperty.createRecord({id: 'name2_site2', 
propertyDependedBy: [{
-          type: 'site3',
-          name: 'name3'
-        },
-        {
-          type: 'site4',
-          name: 'name4'
-        }]
-      });
-      App.StackConfigProperty.createRecord({id: 'name3_site3', 
propertyDependedBy: []});
-      App.StackConfigProperty.createRecord({id: 'name4_site4', 
propertyDependedBy: []});
-    });
-
-    it('adds all file names that need to be loaded to dependentFileNames', 
function() {
-      
mainServiceInfoConfigsController.calculateDependentFileNames(App.StackConfigProperty.find('name1_site1'));
-      
expect(mainServiceInfoConfigsController.get('dependentFileNames').toArray()).to.eql(["site2",
 "site3", "site4"]);
-    });
-  });
-
-  describe('#getServiceNamesForConfigs()', function() {
-    it('returns serviceNames which configs need to be loaded', function() {
-      mainServiceInfoConfigsController.set('content', {});
-      mainServiceInfoConfigsController.set('content.serviceName', 
'currentService');
-      mainServiceInfoConfigsController.set('dependentFileNames', ['site1', 
'site2']);
-      App.resetDsStoreTypeMap(App.StackService);
-      App.StackService.createRecord({id: 'service1', serviceName: 'service1', 
configTypes: {'site1':'site1'}});
-      App.StackService.createRecord({id: 'service2', serviceName: 'service2', 
configTypes: {'site1':'site1', 'site2': 'site2'}});
-      App.StackService.createRecord({id: 'service3', serviceName: 'service3', 
configTypes: {'site3':'site3'}});
-      
expect(mainServiceInfoConfigsController.getServiceNamesForConfigs()).to.eql(['service1',
 'service2', 'currentService']);
-    });
-
-
-  });
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/9f87c98d/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 eacfea5..babbd3b 100644
--- a/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
+++ b/ambari-web/test/mixins/common/configs/enhanced_configs_test.js
@@ -22,22 +22,25 @@ describe('App.EnhancedConfigsMixin', function() {
 
   var mixinObject =  Em.Controller.extend(App.EnhancedConfigsMixin, {});
   var instanceObject = mixinObject.create({});
-  describe('#getFileNamesToSave()', function() {
+  var stackProperty
+  describe('#_getFileNamesToSave()', function() {
 
     beforeEach(function() {
       App.resetDsStoreTypeMap(App.ConfigProperty);
+      App.resetDsStoreTypeMap(App.StackConfigProperty);
+      stackProperty = App.ConfigProperty.createRecord({id: '1', serviceName: 
'service1'});
     });
 
     it('returns file names that was changed', function() {
-      App.ConfigProperty.createRecord({id: 'p1_c1', value:'1', defaultValue: 
'2', fileName: 'file1'});
-      App.ConfigProperty.createRecord({id: 'p2_c1', value:'1', defaultValue: 
'1', fileName: 'file2'});
-      
expect(instanceObject.getFileNamesToSave(['file3'])).to.eql(['file1','file3'])
+      App.ConfigProperty.createRecord({id: 'p1_c1', value:'1', defaultValue: 
'2', fileName: 'file1', stackConfigProperty: stackProperty});
+      App.ConfigProperty.createRecord({id: 'p2_c1', value:'1', defaultValue: 
'1', fileName: 'file2', stackConfigProperty: stackProperty});
+      expect(instanceObject._getFileNamesToSave('service1')).to.eql(['file1'])
     });
 
-    it('returns file names that was changed by adding property', function() {
-      App.ConfigProperty.createRecord({id: 'p1_c1', value:'1', defaultValue: 
'1', fileName: 'file1', isNotSaved: false});
-      App.ConfigProperty.createRecord({id: 'p2_c1', value:'1', defaultValue: 
'1', fileName: 'file2', isNotSaved: true});
-      
expect(instanceObject.getFileNamesToSave(['file3'])).to.eql(['file2','file3'])
+    it('returns file names that was changed for current service', function() {
+      App.ConfigProperty.createRecord({id: 'p1_c1', value:'7', defaultValue: 
'1', fileName: 'file1', stackConfigProperty: stackProperty});
+      App.ConfigProperty.createRecord({id: 'p2_c1', value:'8', defaultValue: 
'1', fileName: 'file2'});
+      expect(instanceObject._getFileNamesToSave('service1')).to.eql(['file1'])
     });
   });
 

Reply via email to