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
           });
         }

Reply via email to