AMBARI-3844. Error in saving host for newly created config group. (akovalenko)
diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js
index 71e56f7..b7986cb 100644
--- a/ambari-web/app/controllers/main/service/item.js
+++ b/ambari-web/app/controllers/main/service/item.js
@@ -244,25 +244,31 @@
         console.log("manageConfigurationGroups(): Saving modified config-groups: ", modifiedConfigGroups);
         var self = this;
         var errors = [];
-        var putCount = modifiedConfigGroups.length;
+        var clearHostsPutCount = modifiedConfigGroups.toClearHosts.length;
+        var setHostsPutCount = modifiedConfigGroups.toSetHosts.length;
         var finishFunction = function(error) {
           if (error != null) {
             errors.push(error);
           }
-          if (--putCount <= 0) {
-            // Done with all the PUTs
-            if (errors.length > 0) {
-              console.log(errors);
-              self.get('subViewController').set('errorMessage',
-                  errors.join(". "));
+          if (--clearHostsPutCount <= 0) {
+            // Done with all the clear hosts PUTs
+            if (--setHostsPutCount < 0) {
+              // Done with all the PUTs
+              if (errors.length > 0) {
+                console.log(errors);
+                self.get('subViewController').set('errorMessage',
+                    errors.join(". "));
+              } else {
+                self.hide();
+              }
             } else {
-              self.hide();
+              App.config.updateConfigurationGroup(modifiedConfigGroups.toSetHosts[setHostsPutCount], finishFunction, finishFunction);
             }
           }
         };
         this.updateConfigGroupOnServicePage();
-        modifiedConfigGroups.forEach(function(cg) {
-          App.config.updateConfigurationGroup(cg, finishFunction, finishFunction);
+        modifiedConfigGroups.toClearHosts.forEach(function (cg) {
+          App.config.clearConfigurationGroupHosts(cg, finishFunction, finishFunction);
         });
       },
       onSecondary: function () {
diff --git a/ambari-web/app/controllers/main/service/manage_config_groups_controller.js b/ambari-web/app/controllers/main/service/manage_config_groups_controller.js
index 97b7f10..0055431 100644
--- a/ambari-web/app/controllers/main/service/manage_config_groups_controller.js
+++ b/ambari-web/app/controllers/main/service/manage_config_groups_controller.js
@@ -33,6 +33,8 @@
 
   selectedHosts: [],
 
+  loadedHostsToGroupMap: {},
+
   loadConfigGroups: function (serviceName) {
     this.set('serviceName', serviceName);
     App.ajax.send({
@@ -47,6 +49,7 @@
   },
 
   onLoadConfigGroupsSuccess: function (data) {
+    var loadedHostsToGroupMap = this.get('loadedHostsToGroupMap');
     var usedHosts = [];
     var unusedHosts = [];
     var defaultConfigGroup = App.ConfigGroup.create({
@@ -63,11 +66,7 @@
       data.items.forEach(function (configGroup) {
         configGroup = configGroup.ConfigGroup;
         var hostNames = configGroup.hosts.mapProperty('host_name');
-        var loadedHostNamesMap = {};
-        hostNames.forEach(function(h){
-          loadedHostNamesMap[h] = true;
-        });
-        loadedHostNamesMap.length = hostNames.length;
+        loadedHostsToGroupMap[configGroup.group_name] = hostNames.slice();
         var newConfigGroup = App.ConfigGroup.create({
           id: configGroup.id,
           name: configGroup.group_name,
@@ -78,9 +77,7 @@
           hosts: hostNames,
           configSiteTags: [],
           properties: [],
-          apiResponse: configGroup,
-          loadedHostNamesMap: loadedHostNamesMap,
-          hostsModified: false
+          apiResponse: configGroup
         });
         usedHosts = usedHosts.concat(newConfigGroup.get('hosts'));
         configGroups.push(newConfigGroup);
@@ -219,6 +216,7 @@
     this.set('selectedHosts', selectedConfigGroup.get('hosts'));
     this.deleteHosts();
     this.get('configGroups').removeObject(selectedConfigGroup);
+    delete this.get('loadedHostsToGroupMap')[selectedConfigGroup.get('name')];
     this.set('selectedConfigGroup', this.get('configGroups').findProperty('isDefault'));
   },
 
@@ -304,23 +302,20 @@
    * On successful api resonse for creating new config group
    */
   onAddNewConfigGroup: function (data) {
-    var loadedHostNamesMap = {};
-    loadedHostNamesMap.length = 0;
-    var defaultConfigGroup = this.get('configGroups').popObject();
+    var defaultConfigGroup = this.get('configGroups').findProperty('isDefault');
     var newConfigGroupData = App.ConfigGroup.create({
       id: data.resources[0].ConfigGroup.id,
       name: this.get('configGroupName'),
       description: this.get('configGroupDesc'),
       isDefault: false,
       parentConfigGroup: defaultConfigGroup,
-      service: this.get('serviceName'),
+      service: App.Service.find().findProperty('serviceName', this.get('serviceName')),
       hosts: [],
-      configSiteTags: [],
-      loadedHostNamesMap: loadedHostNamesMap,
-      hostsModified: false
+      configSiteTags: []
     });
+    this.get('loadedHostsToGroupMap')[newConfigGroupData.get('name')] = [];
     defaultConfigGroup.get('childConfigGroups').push(newConfigGroupData);
-    this.get('configGroups').pushObjects([newConfigGroupData, defaultConfigGroup]);
+    this.get('configGroups').pushObject(newConfigGroupData);
     this.updateConfigGroup(data.resources[0].ConfigGroup.id);
     this.addGroupPopup.hide();
   },
@@ -354,51 +349,29 @@
     this.get('addGroupPopup').set('configGroupDesc', this.get('selectedConfigGroup.description') + ' (Copy)');
   },
 
-  hostsModifiedConfigGroups: function() {
+  hostsModifiedConfigGroups: function () {
+    var groupsToClearHosts = [];
+    var groupsToSetHosts = [];
     var groups = this.get('configGroups');
-    var hostsRemovedGroup = [];
-    var hostsAddedGroup = [];
-    var hostsChangedGroup = [];
-    groups.forEach(function(g) {
-      if (!g.get('isDefault')) {
-        var loadedMap = g.get('loadedHostNamesMap');
-        var current = g.get('hosts');
-        var currentLength = current ? current.length : 0;
-        if (currentLength == loadedMap.length) {
-          if (currentLength>0) {
-            var changed = false;
-            current.forEach(function(c) {
-              if (!changed && loadedMap[c] == null) {
-                changed = true;
-              }
-            });
-            if (changed) {
-              hostsChangedGroup.push(g);
-            }
-          }
-        } else {
-          if (currentLength < loadedMap.length) {
-            hostsRemovedGroup.push(g);
-          } else {
-            hostsAddedGroup.push(g);
+    var loadedHostsToGroupMap = this.get('loadedHostsToGroupMap');
+    groups.forEach(function (group) {
+      if (!group.get('isDefault')) {
+        if (!(JSON.stringify(group.get('hosts').slice().sort()) === JSON.stringify(loadedHostsToGroupMap[group.get('name')].sort()))) {
+          groupsToClearHosts.push(group);
+          if (group.get('hosts').length) {
+            groupsToSetHosts.push(group);
           }
         }
       }
     });
-    // First PUT removed hosts, then PUT added hosts, then changed hosts
-    var modifiedGroups = [];
-    modifiedGroups = modifiedGroups.concat(hostsRemovedGroup);
-    modifiedGroups = modifiedGroups.concat(hostsAddedGroup);
-    modifiedGroups = modifiedGroups.concat(hostsChangedGroup);
-    return modifiedGroups;
+    return {
+      toClearHosts: groupsToClearHosts,
+      toSetHosts: groupsToSetHosts
+    };
   }.property('selectedConfigGroup', 'selectedConfigGroup.hosts.@each'),
   
   isHostsModified: function () {
-    var groups = this.get('hostsModifiedConfigGroups');
-    return groups && groups.length > 0;
-  }.property('hostsModifiedConfigGroups', 'hostsModifiedConfigGroups.length'),
-
-  isDeleteGroupDisabled: function () {
-    return this.get('selectedConfigGroup.isDefault');
-  }.property('selectedConfigGroup')
+    var modifiedGroups = this.get('hostsModifiedConfigGroups');
+    return !!(modifiedGroups.toClearHosts.length || modifiedGroups.toSetHosts.length);
+  }.property('hostsModifiedConfigGroups', 'hostsModifiedConfigGroups.length')
 });
diff --git a/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs b/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs
index 19098fa..7927bd6 100644
--- a/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs
+++ b/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs
@@ -29,13 +29,13 @@
           class="group-select"
         }}
         <div class="btn-toolbar pull-right">
-          <button rel="button-info" class="btn" {{bindAttr data-original-title="view.addButtonTooltip" disabled="isHostsModified"}}
+          <button rel="button-info" class="btn" {{bindAttr data-original-title="view.addButtonTooltip"}}
             {{action addConfigGroup target="controller"}}><i class="icon-plus"></i></button>
           <button rel="button-info" class="btn" {{bindAttr data-original-title="view.removeButtonTooltip" disabled="view.isRemoveButtonDisabled"}}
             {{action confirmDelete target="controller"}}><i class="icon-minus"></i></button>
           <div class="btn-group">
-            <button class="btn" {{bindAttr disabled="isHostsModified"}}><i class="icon-cog"></i></button>
-            <button class="btn dropdown-toggle" data-toggle="dropdown" {{bindAttr disabled="isHostsModified"}}>
+            <button class="btn"><i class="icon-cog"></i></button>
+            <button class="btn dropdown-toggle" data-toggle="dropdown">
               <span class="caret"></span>
             </button>
             <ul class="dropdown-menu">
diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js
index 93fade3..3a849e3 100644
--- a/ambari-web/app/utils/config.js
+++ b/ambari-web/app/utils/config.js
@@ -1235,6 +1235,12 @@
     App.ajax.send(sendData);
   },
 
+  clearConfigurationGroupHosts: function (configGroup, successCallback, errorCallback) {
+    configGroup = jQuery.extend({}, configGroup);
+    configGroup.set('hosts', []);
+    this.updateConfigurationGroup(configGroup, successCallback, errorCallback);
+  },
+
   /**
    * Gets all the configuration-groups for the given service.
    * 
diff --git a/ambari-web/app/views/main/service/manage_config_groups_view.js b/ambari-web/app/views/main/service/manage_config_groups_view.js
index d1a1d5b..9c4de24 100644
--- a/ambari-web/app/views/main/service/manage_config_groups_view.js
+++ b/ambari-web/app/views/main/service/manage_config_groups_view.js
@@ -31,7 +31,7 @@
   //Disable actions remove and rename for Default config group
   buttonObserver: function () {
     var selectedConfigGroup = this.get('controller.selectedConfigGroup');
-    if(selectedConfigGroup.isDefault || this.get('controller.isHostsModified')){
+    if(selectedConfigGroup.isDefault){
       this.set('isRemoveButtonDisabled', true);
       this.set('isRenameButtonDisabled', true);
     }else{