Repository: ambari Updated Branches: refs/heads/trunk e82561dc4 -> 76ad10f4a
AMBARI-6464. FE: Saving of configs with final flags checked should persist on Ambari Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/76ad10f4 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/76ad10f4 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/76ad10f4 Branch: refs/heads/trunk Commit: 76ad10f4a6f10aa9e4ee5b3b2e903d4e28a9f08a Parents: e82561d Author: Srimanth Gunturi <sgunt...@hortonworks.com> Authored: Thu Jul 10 17:42:38 2014 -0700 Committer: Srimanth Gunturi <sgunt...@hortonworks.com> Committed: Thu Jul 10 22:56:50 2014 -0700 ---------------------------------------------------------------------- .../global/configuration_controller.js | 1 + .../controllers/main/service/info/configs.js | 171 ++++++++++++++++--- ambari-web/app/messages.js | 1 + ambari-web/app/models/service_config.js | 2 + ambari-web/app/styles/application.less | 9 + .../templates/common/configs/service_config.hbs | 3 + ambari-web/app/utils/ajax/ajax.js | 4 + ambari-web/app/utils/config.js | 10 +- 8 files changed, 174 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/ambari-web/app/controllers/global/configuration_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/configuration_controller.js b/ambari-web/app/controllers/global/configuration_controller.js index 3e01572..f5aaa7a 100644 --- a/ambari-web/app/controllers/global/configuration_controller.js +++ b/ambari-web/app/controllers/global/configuration_controller.js @@ -73,6 +73,7 @@ App.ConfigurationController = Em.Controller.extend({ if (storedSite) { storedSite.tag = loadedSite.tag; storedSite.properties = loadedSite.properties; + storedSite.properties_attributes = loadedSite.properties_attributes; } else { storedConfigs.push(loadedSite); } http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/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 5b0dbcd..eaefd2d 100644 --- a/ambari-web/app/controllers/main/service/info/configs.js +++ b/ambari-web/app/controllers/main/service/info/configs.js @@ -30,6 +30,8 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ selectedService: null, serviceConfigTags: null, selectedConfigGroup: null, + selectedServiceConfigTypes: [], + selectedServiceSupportsFinal: [], configGroups: [], globalConfigs: [], uiConfigs: [], @@ -182,8 +184,32 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ loadServiceConfigs: function () { var advancedConfigs = []; var self = this; + var serviceName = this.get('content.serviceName'); + + var stackService = App.StackService.find().findProperty('serviceName', serviceName); + if (stackService != null) { + var configTypes = stackService.get('configTypes'); + if (configTypes) { + var configTypesInfo = { + items : [], + supportsFinal : [] + }; + for ( var key in configTypes) { + if (configTypes.hasOwnProperty(key)) { + configTypesInfo.items.push(key); + if (configTypes[key].supports && configTypes[key].supports.final === "true") { + configTypesInfo.supportsFinal.push(key); + } + } + } + for ( var configType in configTypes) { + self.set('selectedServiceConfigTypes', configTypesInfo.items || []); + self.set('selectedServiceSupportsFinal', configTypesInfo.supportsFinal || []); + } + } + } - App.config.loadAdvancedConfig(this.get('content.serviceName'), function (properties) { + App.config.loadAdvancedConfig(serviceName, function (properties) { advancedConfigs.pushObjects(properties); self.set('advancedConfigs', advancedConfigs); self.loadServiceTags(); @@ -578,6 +604,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ this.setValidator(serviceConfigProperty, serviceConfigsData); this.setValuesForOverrides(overrides, _serviceConfigProperty, serviceConfigProperty, defaultGroupSelected); this.setEditability(serviceConfigProperty, defaultGroupSelected); + this.setSupportsFinal(serviceConfigProperty); return serviceConfigProperty; }, @@ -653,6 +680,19 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ }, /** + * set supportsFinal property of config for admin + * @param {Ember.Object} serviceConfigProperty + * @method setSupportsFinal + */ + setSupportsFinal: function (serviceConfigProperty) { + var fileName = serviceConfigProperty.get('filename'); + var matchingConfigTypes = this.get('selectedServiceSupportsFinal').filter(function(configType) { + return fileName.startsWith(configType); + }); + serviceConfigProperty.set('supportsFinal', matchingConfigTypes.length > 0); + }, + + /** * set serviceValidator for config property * hide properties for other services * @param {Ember.Object} serviceConfigProperty @@ -1433,14 +1473,18 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ */ createConfigObject: function (siteName, tagName) { console.log("TRACE: Inside " + siteName); + var configObject; switch (siteName) { case 'global': - return this.createGlobalSiteObj(tagName, this.get('globalConfigs')); + configObject = this.createGlobalSiteObj(tagName, this.get('globalConfigs')); + break; case 'core-site': if (this.get('content.serviceName') === 'HDFS' || this.get('content.serviceName') === 'GLUSTERFS') { - return this.createCoreSiteObj(tagName); + configObject = this.createCoreSiteObj(tagName); + } else { + return null; } - return null; + break; default: var filename = (App.config.get('filenameExceptions').contains(siteName)) ? siteName : siteName + '.xml'; if (filename === 'mapred-queue-acls.xml' && !App.supports.capacitySchedulerUi) { @@ -1448,28 +1492,27 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ } return this.createSiteObj(siteName, tagName, this.get('uiConfigs').filterProperty('filename', filename)); } + return configObject; }, /** * load existen properties and compare them with current if there are * differences - trigger doPUTClusterConfigurationSite to save new properties * @param {String} siteName - * @param {Object} configs + * @param {Object} newConfig * @method doPUTClusterConfiguration */ - doPUTClusterConfiguration: function (siteName, configs) { - var loadedProperties; - loadedProperties = App.router.get('configurationController').getConfigsByTags([ + doPUTClusterConfiguration: function (siteName, newConfig) { + var oldConfig = App.router.get('configurationController').getConfigsByTags([ {siteName: siteName, tagName: this.loadedClusterSiteToTagMap[siteName]} ]); - if (loadedProperties && loadedProperties[0]) { - loadedProperties = loadedProperties[0].properties; - } - if (!loadedProperties) { - loadedProperties = {}; - } - if (this.isConfigChanged(loadedProperties, configs.properties)) { - this.doPUTClusterConfigurationSite(configs); + oldConfig = oldConfig[0] || {}; + var oldProperties = oldConfig.properties || {}; + var oldAttributes = oldConfig["properties_attributes"] || {}; + var newProperties = newConfig.properties || {}; + var newAttributes = newConfig["properties_attributes"] || {}; + if (this.isAttributesChanged(oldAttributes, newAttributes) || this.isConfigChanged(oldProperties, newProperties)) { + this.doPUTClusterConfigurationSite(newConfig); } else { if (this.decrementProperty('putClusterConfigsCallsNumber') === 0) { this.onDoPUTClusterConfigurations(); @@ -1493,7 +1536,6 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ * @method isConfigChanged */ isConfigChanged: function (loadedConfig, savingConfig) { - var changed = false; if (loadedConfig != null && savingConfig != null) { var seenLoadKeys = []; for (var loadKey in loadedConfig) { @@ -1508,18 +1550,59 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ saveValue = "null"; } if (loadValue !== saveValue) { - changed = true; - break; + return true; } } for (var saveKey in savingConfig) { if (seenLoadKeys.indexOf(saveKey) < 0) { - changed = true; - break; + return true; } } } - return changed; + return false; + }, + + /** + * Compares the loaded config properties attributes with the saving config properties attributes. + * @param {Object} oldAttributes - + * oldAttributes: { + * supports: { + * final: { + * "configValue1" : "true", + * "configValue2" : "true" + * } + * } + * } + * @param {Object} newAttributes + * newAttributes: { + * supports: { + * final: { + * "configValue1" : "true", + * "configValue2" : "true" + * } + * } + * } + * @returns {boolean} + * @method isConfigChanged + */ + isAttributesChanged: function (oldAttributes, newAttributes) { + oldAttributes = oldAttributes.final || {}; + newAttributes = newAttributes.final || {}; + + var key; + for (key in oldAttributes) { + if (oldAttributes.hasOwnProperty(key) + && (!newAttributes.hasOwnProperty(key) || newAttributes[key] !== oldAttributes[key])) { + return true; + } + } + for (key in newAttributes) { + if (newAttributes.hasOwnProperty(key) + && (!oldAttributes.hasOwnProperty(key) || newAttributes[key] !== oldAttributes[key])) { + return true; + } + } + return false; }, /** @@ -1568,6 +1651,29 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ }, /** + * Save "final" attribute for properties + * @param {Array} properties - array of properties + * @returns {Object|null} + * */ + getConfigAttributes: function(properties) { + var attributes = { + final: {} + }; + var finalAttributes = attributes.final; + var hasAttributes = false; + properties.forEach(function (property) { + if (property.isRequiredByAgent !== false && property.isFinal) { + hasAttributes = true; + finalAttributes[property.name] = "true"; + } + }); + if (hasAttributes) { + return attributes; + } + return null; + }, + + /** * create global site object * @param {String} tagName * @param {Array} globalConfigs array of config objects @@ -1590,7 +1696,12 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ //console.log("TRACE: value of the global property is: " + _globalSiteObj.value); } }, this); - return {"type": "global", "tag": tagName, "properties": globalSiteProperties}; + var result = {"type": "global", "tag": tagName, "properties": globalSiteProperties}; + var attributes = this.getConfigAttributes(globalConfigs); + if (attributes) { + result['properties_attributes'] = attributes; + } + return result; }, /** @@ -1606,7 +1717,12 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ coreSiteProperties[_coreSiteObj.name] = App.config.escapeXMLCharacters(_coreSiteObj.value); //this.recordHostOverride(_coreSiteObj, 'core-site', tagName, this); }, this); - return {"type": "core-site", "tag": tagName, "properties": coreSiteProperties}; + var result = {"type": "core-site", "tag": tagName, "properties": coreSiteProperties}; + var attributes = this.getConfigAttributes(coreSiteObj); + if (attributes) { + result['properties_attributes'] = attributes; + } + return result; }, /** @@ -1629,7 +1745,12 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({ siteProperties[_siteObj.name] = this.setServerConfigValue(_siteObj.name, _siteObj.value); } }, this); - return {"type": siteName, "tag": tagName, "properties": siteProperties}; + var result = {"type": siteName, "tag": tagName, "properties": siteProperties}; + var attributes = this.getConfigAttributes(siteObj); + if (attributes) { + result['properties_attributes'] = attributes; + } + return result; }, /** * This method will be moved to config's decorators class. http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 0277d13..85c893a 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -1275,6 +1275,7 @@ Em.I18n.translations = { 'services.service.info.summary.nagios.noAlerts':'No alerts', 'services.service.info.summary.nagios.alerts':'Nagios service required for viewing alerts', + 'services.service.config.final':'Final', 'services.service.config.saved':'Save Configuration Changes', 'services.service.config.notSaved':'Unable to Save Configuration Changes', 'services.service.config.restartService.TooltipMessage':'<b>Restart Service</b><br>Stale configuration used by {0} components on {1} hosts:{2}', http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/ambari-web/app/models/service_config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/service_config.js b/ambari-web/app/models/service_config.js index 330514c..9e6823c 100644 --- a/ambari-web/app/models/service_config.js +++ b/ambari-web/app/models/service_config.js @@ -146,6 +146,8 @@ App.ServiceConfigProperty = Ember.Object.extend({ isRequired: true, // by default a config property is required isReconfigurable: true, // by default a config property is reconfigurable isEditable: true, // by default a config property is editable + isFinal: false, + supportsFinal: false, isVisible: true, isRequiredByAgent: true, // Setting it to true implies property will be stored in global configuration isSecureConfig: false, http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index d1bdb55..70ced0e 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -1060,6 +1060,12 @@ h1 { padding: 5px; margin-left: -5px; } + .checkbox.inline { + vertical-align: baseline; + &>.ember-checkbox{ + margin-left: -14px; + } + } } .entry-row { margin: 10px 0; @@ -1087,6 +1093,9 @@ h1 { } .error { } + &>.ember-checkbox{ + margin-bottom: 5px; + } } } form { http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/ambari-web/app/templates/common/configs/service_config.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/common/configs/service_config.hbs b/ambari-web/app/templates/common/configs/service_config.hbs index 6f085ab..545da24 100644 --- a/ambari-web/app/templates/common/configs/service_config.hbs +++ b/ambari-web/app/templates/common/configs/service_config.hbs @@ -135,6 +135,9 @@ <a class="action" {{action "removeProperty" this target="view" }} ><i class="icon-minus-sign"></i>{{t common.remove}}</a> {{/if}} {{/if}} + {{#if supportsFinal}} + <label class="checkbox inline">{{view Ember.Checkbox checkedBinding="isFinal"}}{{t services.service.config.final}}</label> + {{/if}} {{/if}} <span class="help-inline">{{errorMessage}}</span> <span class="help-inline">{{warnMessage}}</span> http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/ambari-web/app/utils/ajax/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js index b759c4a..a0aaab1 100644 --- a/ambari-web/app/utils/ajax/ajax.js +++ b/ambari-web/app/utils/ajax/ajax.js @@ -315,6 +315,10 @@ var urls = { 'real': '{stackVersionUrl}/services/{serviceName}/configurations?fields=*', 'mock': '/data/wizard/stack/hdp/version{stackVersion}/{serviceName}.json' }, + 'config.config_types': { + 'real': '{stackVersionUrl}/services/{serviceName}?fields=StackServices/config_types', + 'mock': '' + }, 'config.tags': { 'real': '/clusters/{clusterName}?fields=Clusters/desired_configs', 'mock': '/data/clusters/cluster.json' http://git-wip-us.apache.org/repos/asf/ambari/blob/76ad10f4/ambari-web/app/utils/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js index abdc19c..7db38c1 100644 --- a/ambari-web/app/utils/config.js +++ b/ambari-web/app/utils/config.js @@ -303,11 +303,14 @@ App.config = Em.Object.create({ tags.forEach(function (_tag) { var isAdvanced = null; var filename = (filenameExceptions.contains(_tag.siteName)) ? _tag.siteName : _tag.siteName + ".xml"; - var properties = configGroups.filter(function (serviceConfigProperties) { + var siteConfig = configGroups.filter(function (serviceConfigProperties) { return _tag.tagName === serviceConfigProperties.tag && _tag.siteName === serviceConfigProperties.type; }); + siteConfig = siteConfig[0] || {}; - properties = (properties.length) ? properties.objectAt(0).properties : {}; + var attributes = siteConfig['properties_attributes'] || {}; + var finalAttributes = attributes.final || {}; + var properties = siteConfig.properties || {}; for (var index in properties) { var configsPropertyDef = null; var preDefinedConfig = []; @@ -336,6 +339,7 @@ App.config = Em.Object.create({ isUserProperty: false, isOverridable: true, isRequired: true, + isFinal: finalAttributes[index] === "true", showLabel: true, serviceName: serviceName, belongsToService: [] @@ -808,6 +812,7 @@ App.config = Em.Object.create({ }, this); } }, + /** * Generate serviceProperties save it to localDB * called form stepController step6WizardController @@ -854,6 +859,7 @@ App.config = Em.Object.create({ value: item.property_value, description: item.property_description, isVisible: item.isVisible, + isFinal: item.final === "true", filename: item.filename || fileName }); }