Updated Branches: refs/heads/trunk c46beb2bf -> e9a1ba1ee
AMBARI-3783. Hitting Save in the config-group does not update host membership. (srimanth) Project: http://git-wip-us.apache.org/repos/asf/incubator-ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ambari/commit/e9a1ba1e Tree: http://git-wip-us.apache.org/repos/asf/incubator-ambari/tree/e9a1ba1e Diff: http://git-wip-us.apache.org/repos/asf/incubator-ambari/diff/e9a1ba1e Branch: refs/heads/trunk Commit: e9a1ba1ee616450053d5515c21fc67d4a705b0af Parents: c46beb2 Author: Srimanth Gunturi <sgunt...@hortonworks.com> Authored: Fri Nov 15 18:25:02 2013 -0800 Committer: Srimanth Gunturi <sgunt...@hortonworks.com> Committed: Mon Nov 18 10:05:51 2013 -0800 ---------------------------------------------------------------------- ambari-web/app/config.js | 2 +- ambari-web/app/controllers/main/service/item.js | 32 +++++++++- .../service/manage_config_groups_controller.js | 64 ++++++++++++++++++-- ambari-web/app/styles/application.less | 15 ++++- .../manage_configuration_groups_popup.hbs | 39 +++++++++--- ambari-web/app/utils/ajax.js | 11 ++++ ambari-web/app/utils/config.js | 59 ++++++++++++++++++ 7 files changed, 205 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e9a1ba1e/ambari-web/app/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/config.js b/ambari-web/app/config.js index b9f869d..52a0080 100644 --- a/ambari-web/app/config.js +++ b/ambari-web/app/config.js @@ -44,7 +44,7 @@ App.enableExperimental = false; App.supports = { addServices: false, - hostOverrides: false, + hostOverrides: true, mirroring: false, secureCluster: true, secureClusterProceedPopup: false, http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e9a1ba1e/ambari-web/app/controllers/main/service/item.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js index ca9ca35..e087462 100644 --- a/ambari-web/app/controllers/main/service/item.js +++ b/ambari-web/app/controllers/main/service/item.js @@ -227,8 +227,38 @@ App.MainServiceItemController = Em.Controller.extend({ classNames: ['sixty-percent-width-modal', 'manage-configuration-group-popup'], primary: Em.I18n.t('common.save'), onPrimary: function() { - this.hide(); + // Save modified config-groups + var modifiedConfigGroups = this.get('subViewController.hostsModifiedConfigGroups'); + console.log("manageConfigurationGroups(): Saving modified config-groups: ", modifiedConfigGroups); + var self = this; + var errors = []; + var putCount = modifiedConfigGroups.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(". ")); + } else { + self.hide(); + } + } + }; + modifiedConfigGroups.forEach(function(cg) { + App.config.updateConfigurationGroup(cg, finishFunction, finishFunction); + }); }, + subViewController: function(){ + return App.router.get('manageConfigGroupsController'); + }.property('App.router.manageConfigGroupsController'), + updateButtons: function(){ + var modified = this.get('subViewController.isHostsModified'); + this.set('enablePrimary', modified); + }.observes('subViewController.isHostsModified'), secondary : Em.I18n.t('common.cancel'), didInsertElement: function () {} }); http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e9a1ba1e/ambari-web/app/controllers/main/service/manage_config_groups_controller.js ---------------------------------------------------------------------- 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 0ac5bc0..90164f0 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 @@ -62,6 +62,12 @@ App.ManageConfigGroupsController = Em.Controller.extend({ var configGroups = []; 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; var newConfigGroup = App.ConfigGroup.create({ id: configGroup.id, name: configGroup.group_name, @@ -69,10 +75,12 @@ App.ManageConfigGroupsController = Em.Controller.extend({ isDefault: false, parentConfigGroup: defaultConfigGroup, service: App.Service.find().findProperty('serviceName', configGroup.tag), - hosts: configGroup.hosts.mapProperty('host_name'), + hosts: hostNames, configSiteTags: [], properties: [], - apiResponse: configGroup + apiResponse: configGroup, + loadedHostNamesMap: loadedHostNamesMap, + hostsModified: false }); usedHosts = usedHosts.concat(newConfigGroup.get('hosts')); configGroups.push(newConfigGroup); @@ -277,6 +285,8 @@ App.ManageConfigGroupsController = Em.Controller.extend({ * On successful api resonse for creating new config group */ onAddNewConfigGroup: function (data) { + var loadedHostNamesMap = {}; + loadedHostNamesMap.length = 0; var newConfigGroupData = App.ConfigGroup.create({ id: data.resources[0].ConfigGroup.id, name: this.get('configGroupName'), @@ -285,7 +295,9 @@ App.ManageConfigGroupsController = Em.Controller.extend({ parentConfigGroup: null, service: this.get('serviceName'), hosts: [], - configSiteTags: [] + configSiteTags: [], + loadedHostNamesMap: loadedHostNamesMap, + hostsModified: false }); var defaultConfigGroup = this.get('configGroups').popObject(); this.get('configGroups').pushObjects([newConfigGroupData, defaultConfigGroup]); @@ -310,5 +322,49 @@ App.ManageConfigGroupsController = Em.Controller.extend({ successLoadingConfigGroup: function (data) { var confGroup = this.get('configGroups').findProperty('id', data.ConfigGroup.id); confGroup.set('apiResponse', data.ConfigGroup); - } + }, + + hostsModifiedConfigGroups: function() { + 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); + } + } + } + }); + // 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; + }.property('selectedConfigGroup', 'selectedConfigGroup.hosts.@each'), + + isHostsModified: function () { + var groups = this.get('hostsModifiedConfigGroups'); + return groups && groups.length > 0; + }.property('hostsModifiedConfigGroups', 'hostsModifiedConfigGroups.length') }); http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e9a1ba1e/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index 4346c9b..3043e0a 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -4889,7 +4889,20 @@ i.icon-asterisks { } .manage-configuration-group-popup { + .modal{ + max-height: 600px; + } + .modal-body { + max-height: 450px; + } .group-select { - width: 100% + width: 100%; + height: 250px; + } + .btn-toolbar { + margin-top: 0px; + } + .manage-configuration-group-content { + margin-bottom: 30px; } } http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e9a1ba1e/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs ---------------------------------------------------------------------- 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 857dd18..9b1d1fa 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 @@ -16,11 +16,11 @@ * limitations under the License. }} <div class="alert alert-info">{{t services.service.config_groups_popup.notice}}</div> -<div class="row-fluid"> +<div class="row-fluid manage-configuration-group-content"> <div class="span12"> {{t services.service.config_groups_popup.config_groups}} <div class="row-fluid"> - <div class="span6"> + <div class="span5"> {{view Em.Select contentBinding="configGroups" optionLabelPath="content.displayName" @@ -28,14 +28,26 @@ multiple="multiple" class="group-select" }} - <div class="button-group pull-right"> - <a class="btn" {{action addConfigGroup target="controller"}}>+</a> - <a class="btn" {{action deleteConfigGroup target="controller"}}>-</a> - <a class="btn" {{action renameConfigGroup target="controller"}}>{{t services.service.config_groups_popup.rename}}</a> - <a class="btn" {{action addConfigGroup target="controller"}}>{{t services.service.config_groups_popup.duplicate}}</a> + <div class="btn-toolbar pull-right"> + <button class="btn" {{bindAttr disabled="isHostsModified"}} {{action addConfigGroup target="controller"}}><i class="icon-plus"></i></button> + <button class="btn" {{bindAttr disabled="isHostsModified"}} {{action deleteConfigGroup 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"}}> + <span class="caret"></span> + </button> + <ul class="dropdown-menu"> + <li> + <a {{action renameConfigGroup target="controller"}}>{{t services.service.config_groups_popup.rename}}</a> + </li> + <li> + <a {{action addConfigGroup target="controller"}}>{{t services.service.config_groups_popup.duplicate}}</a> + </li> + </ul> + </div> </div> </div> - <div class="span6"> + <div class="span7"> <div class="row-fluid"> <div class="span2">{{t common.hosts}}</div> <div class="span10"> @@ -47,8 +59,8 @@ }} </div> <div class="button-group pull-right"> - <button class="btn" {{bindAttr disabled="selectedConfigGroup.isAddHostsDisabled"}} {{action addHosts target="controller"}} >+</button> - <button class="btn" {{bindAttr disabled="selectedConfigGroup.isDeleteHostsDisabled"}} {{action deleteHosts target="controller"}} >-</button> + <button class="btn" {{bindAttr disabled="selectedConfigGroup.isAddHostsDisabled"}} {{action addHosts target="controller"}} ><i class="icon-plus"></i></button> + <button class="btn" {{bindAttr disabled="selectedConfigGroup.isDeleteHostsDisabled"}} {{action deleteHosts target="controller"}} ><i class="icon-minus"></i></button> </div> </div> <div class="row-fluid"> @@ -59,6 +71,13 @@ </div> </div> </div> + <div class="span12 text-error" id="manage-config-group-error-div"> + {{#if errorMessage}} + {{errorMessage}} + {{else}} + + {{/if}} + </div> </div> </div> </div> http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e9a1ba1e/ambari-web/app/utils/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js index fecc869..9226d4e 100644 --- a/ambari-web/app/utils/ajax.js +++ b/ambari-web/app/utils/ajax.js @@ -1178,6 +1178,17 @@ var urls = { }]) } } + }, + 'config_groups.update': { + 'real': '/clusters/{clusterName}/config_groups/{id}', + 'mock': '', + 'format': function (data) { + return { + async: true, + type: 'PUT', + data: JSON.stringify(data.data) + } + } } }; /** http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e9a1ba1e/ambari-web/app/utils/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js index a6859a5..671e1a3 100644 --- a/ambari-web/app/utils/config.js +++ b/ambari-web/app/utils/config.js @@ -1126,6 +1126,65 @@ App.config = Em.Object.create({ } return newConfigGroupData; }, + + /** + * PUTs the new configuration-group on the server. + * Changes possible here are the name, description and + * host memberships of the configuration-group. + * + * @param configGroup (App.ConfigGroup) Configuration group to update + */ + updateConfigurationGroup: function (configGroup, successCallback, errorCallback) { + var putConfigGroup = { + ConfigGroup: { + group_name: configGroup.get('name'), + description: configGroup.get('description'), + tag: configGroup.get('service.serviceName'), + hosts: [], + desired_configs: [] + } + }; + configGroup.get('hosts').forEach(function(h){ + putConfigGroup.ConfigGroup.hosts.push({ + host_name: h + }); + }); + configGroup.get('configSiteTags').forEach(function(cst){ + putConfigGroup.ConfigGroup.desired_configs.push({ + type: cst.type, + tag: cst.tag + }); + }); + + var sendData = { + name: 'config_groups.update', + data: { + id: configGroup.get('id'), + data: putConfigGroup + }, + success: 'successFunction', + error: 'errorFunction', + successFunction: function () { + if(successCallback) { + successCallback(); + } + }, + errorFunction: function (xhr, text, errorThrown) { + error = xhr.status + "(" + errorThrown + ") "; + try { + var json = $.parseJSON(xhr.responseText); + error += json.message; + } catch (err) { + } + console.error('Error updating Config Group:', error, configGroup); + if(errorCallback) { + errorCallback(error); + } + } + }; + sendData.sender = sendData; + App.ajax.send(sendData); + }, /** * Gets all the configuration-groups for the given service.