You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ab...@apache.org on 2014/05/12 20:15:06 UTC

git commit: AMBARI-5738 Unit test and refactoring for controllers/main/service/info/config.js part 2. (ababiichuk)

Repository: ambari
Updated Branches:
  refs/heads/trunk 55bb122d0 -> 105b41b04


AMBARI-5738 Unit test and refactoring for controllers/main/service/info/config.js part 2. (ababiichuk)


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

Branch: refs/heads/trunk
Commit: 105b41b04c2b4969503c5f93061d47d3a00b8ab0
Parents: 55bb122
Author: aBabiichuk <ab...@cybervisiontech.com>
Authored: Mon May 12 21:12:30 2014 +0300
Committer: aBabiichuk <ab...@cybervisiontech.com>
Committed: Mon May 12 21:13:01 2014 +0300

----------------------------------------------------------------------
 .../controllers/main/service/info/configs.js    | 382 +++++++------
 .../main/service/info/config_test.js            | 553 ++++++++++++++++++-
 2 files changed, 758 insertions(+), 177 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/105b41b0/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 712665f..3d11baf 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -1167,7 +1167,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
   formatConfigValues: function(serviceConfigProperties){
     serviceConfigProperties.forEach(function (_config) {
       if (typeof _config.get('value') === "boolean") _config.set('value', _config.value.toString());
-      _config.set('value', App.config.trimProperty(_config), true);
+      _config.set('value', App.config.trimProperty(_config, true));
     });
   },
 
@@ -1290,71 +1290,77 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
   /**
    * Saves cluster level configurations for all necessary sites.
    * PUT calls are made to /api/v1/clusters/clusterName for each site.
-   *
    * @return {Boolean}
+   * @method doPUTClusterConfigurations
    */
   doPUTClusterConfigurations: function () {
     var result = true;
     var serviceConfigTags = this.get('serviceConfigTags');
     this.setNewTagNames(serviceConfigTags);
     var siteNameToServerDataMap = {};
-    var configController = App.router.get('configurationController');
-    var filenameExceptions = App.config.get('filenameExceptions');
 
     serviceConfigTags.forEach(function (_serviceTags) {
-      var loadedProperties;
-      if (_serviceTags.siteName === 'global') {
-        console.log("TRACE: Inside global");
-        var serverGlobalConfigs = this.createGlobalSiteObj(_serviceTags.newTagName, this.get('globalConfigs'));
-        siteNameToServerDataMap['global'] = serverGlobalConfigs;
-        loadedProperties = configController.getConfigsByTags([{siteName: 'global', tagName: this.loadedClusterSiteToTagMap['global']}]);
-        if (loadedProperties && loadedProperties[0]) {
-          loadedProperties = loadedProperties[0].properties;
-        }
-        if (this.isConfigChanged(loadedProperties, serverGlobalConfigs.properties)) {
-          result = result && this.doPUTClusterConfigurationSite(serverGlobalConfigs);
-        }
-      }
-      else {
-        if (_serviceTags.siteName === 'core-site') {
-          console.log("TRACE: Inside core-site");
-          if (this.get('content.serviceName') === 'HDFS' || this.get('content.serviceName') === 'GLUSTERFS') {
-            var coreSiteConfigs = this.createCoreSiteObj(_serviceTags.newTagName);
-            siteNameToServerDataMap['core-site'] = coreSiteConfigs;
-            loadedProperties = configController.getConfigsByTags([{siteName: 'core-site', tagName: this.loadedClusterSiteToTagMap['core-site']}]);
-            if (loadedProperties && loadedProperties[0]) {
-              loadedProperties = loadedProperties[0].properties;
-            }
-            if (this.isConfigChanged(loadedProperties, coreSiteConfigs.properties)) {
-              result = result && this.doPUTClusterConfigurationSite(coreSiteConfigs);
-            }
-          }
-        }
-        else {
-          var filename = (filenameExceptions.contains(_serviceTags.siteName)) ? _serviceTags.siteName : _serviceTags.siteName + '.xml';
-          var siteConfigs = this.get('uiConfigs').filterProperty('filename', filename);
-          var serverConfigs = this.createSiteObj(_serviceTags.siteName, _serviceTags.newTagName, siteConfigs);
-          siteNameToServerDataMap[_serviceTags.siteName] = serverConfigs;
-          loadedProperties = configController.getConfigsByTags([{siteName: _serviceTags.siteName, tagName: this.loadedClusterSiteToTagMap[_serviceTags.siteName]}]);
-          if (loadedProperties && loadedProperties[0]) {
-            loadedProperties = loadedProperties[0].properties;
-          }
-          if (!loadedProperties) {
-            loadedProperties = {};
-          }
-          if (filename === 'mapred-queue-acls' && !App.supports.capacitySchedulerUi) {
-            return;
-          }
-          if (this.isConfigChanged(loadedProperties, serverConfigs.properties)) {
-            result = result && this.doPUTClusterConfigurationSite(serverConfigs);
-          }
-        }
+      var configs = this.createConfigObject(_serviceTags.siteName, _serviceTags.newTagName);
+      if (configs) {
+        result = result && this.doPUTClusterConfiguration(siteNameToServerDataMap, _serviceTags.siteName, configs);
       }
     }, this);
-    this.savedSiteNameToServerServiceConfigDataMap = siteNameToServerDataMap;
+    this.set("savedSiteNameToServerServiceConfigDataMap", siteNameToServerDataMap);
     return result;
   },
 
+  /**
+   * create different config object depending on siteName
+   * @param {String} siteName
+   * @param {String} tagName
+   * @returns {Object|undefined}
+   * @method createConfigObject
+   */
+  createConfigObject: function(siteName, tagName) {
+    console.log("TRACE: Inside " + siteName);
+    switch(siteName) {
+      case 'global':
+        return this.createGlobalSiteObj(tagName, this.get('globalConfigs'));
+      case 'core-site':
+        if(this.get('content.serviceName') === 'HDFS' || this.get('content.serviceName') === 'GLUSTERFS') {
+          return this.createCoreSiteObj(tagName);
+        }
+        return;
+      default:
+        var filename = (App.config.get('filenameExceptions').contains(siteName)) ? siteName : siteName + '.xml';
+        if (filename === 'mapred-queue-acls.xml' && !App.supports.capacitySchedulerUi) {
+          return;
+        }
+      return this.createSiteObj(siteName, tagName, this.get('uiConfigs').filterProperty('filename', filename));
+    }
+  },
+
+  /**
+   * load existen properties and compare them with current if there are
+   * differences - trigger doPUTClusterConfigurationSite to save new properties
+   * @param {Object} siteNameToServerDataMap
+   * @param {String} siteName
+   * @param {Object} configs
+   * @returns {Boolean} true if config successfully saved or there
+   *                    is no need to save them
+   * @method doPUTClusterConfiguration
+   */
+  doPUTClusterConfiguration: function(siteNameToServerDataMap, siteName, configs) {
+    var loadedProperties;
+    siteNameToServerDataMap[siteName] = configs;
+    loadedProperties = 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)) {
+      return this.doPUTClusterConfigurationSite(configs);
+    }
+    return true;
+  },
+
 
   /**
    * Compares the loaded config values with the saving config values.
@@ -1552,133 +1558,191 @@ App.MainServiceInfoConfigsController = Em.Controller.extend({
   },
 
   /**
+   * Array of Objects
+   * {
+   *  hostProperty - hostName property name for current component
+   *  componentName - master componentName
+   *  serviceName - serviceName of component
+   *  serviceUseThis - services that use hostname property of component(componentName)
+   *  m(multiple) - true if can be more than one components installed on cluster
+   * }
+   */
+
+  hostComponentsmapping: [
+    {
+      hostProperty: 'namenode_host',
+      componentName: 'NAMENODE',
+      serviceName: 'HDFS',
+      serviceUseThis: [],
+      m: true
+    },
+    {
+      hostProperty: 'snamenode_host',
+      componentName: 'SECONDARY_NAMENODE',
+      serviceName: 'HDFS',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'jobtracker_host',
+      componentName: 'JOBTRACKER',
+      serviceName: 'MAPREDUCE',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'jobtracker_host',
+      componentName: 'JOBTRACKER',
+      serviceName: 'MAPREDUCE2',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'hs_host',
+      componentName: 'HISTORYSERVER',
+      serviceName: 'MAPREDUCE2',
+      serviceUseThis: ['YARN']
+    },
+    {
+      hostProperty: 'ats_host',
+      componentName: 'APP_TIMELINE_SERVER',
+      serviceName: 'YARN',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'rm_host',
+      componentName: 'RESOURCEMANAGER',
+      serviceName: 'YARN',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'hivemetastore_host',
+      componentName: 'HIVE_SERVER',
+      serviceName: 'HIVE',
+      serviceUseThis: ['WEBHCAT']
+    },
+    {
+      hostProperty: 'oozieserver_host',
+      componentName: 'OOZIE_SERVER',
+      serviceName: 'OOZIE',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'hbasemaster_host',
+      componentName: 'HBASE_MASTER',
+      serviceName: 'HBASE',
+      serviceUseThis: [],
+      m: true
+    },
+    {
+      hostProperty: 'hueserver_host',
+      componentName: 'HUE_SERVER',
+      serviceName: 'HUE',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'webhcatserver_host',
+      componentName: 'WEBHCAT_SERVER',
+      serviceName: 'WEBHCAT',
+      serviceUseThis: [],
+      m: true
+    },
+    {
+      hostProperty: 'zookeeperserver_hosts',
+      componentName: 'ZOOKEEPER_SERVER',
+      serviceName: 'ZOOKEEPER',
+      serviceUseThis: ['HBASE', 'WEBHCAT'],
+      m: true
+    },
+    {
+      hostProperty: 'stormuiserver_host',
+      componentName: 'STORM_UI_SERVER',
+      serviceName: 'STORM',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'drpcserver_host',
+      componentName: 'DRPC_SERVER',
+      serviceName: 'STORM',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'storm_rest_api_host',
+      componentName: 'STORM_REST_API',
+      serviceName: 'STORM',
+      serviceUseThis: []
+    },
+    {
+      hostProperty: 'supervisor_hosts',
+      componentName: 'SUPERVISOR',
+      serviceName: 'STORM',
+      serviceUseThis: [],
+      m: true
+    }
+  ],
+
+  /**
    * Adds host name of master component to global config;
+   * @method addHostNamesToGlobalConfig
    */
   addHostNamesToGlobalConfig: function () {
     var serviceName = this.get('content.serviceName');
     var globalConfigs = this.get('globalConfigs');
-    var serviceConfigs = this.get('serviceConfigs').findProperty('serviceName', serviceName).configs;
-    var hostComponents = App.HostComponent.find();
     //namenode_host is required to derive "fs.default.name" a property of core-site
-    var nameNodeHost = this.get('serviceConfigs').findProperty('serviceName', 'HDFS').configs.findProperty('name', 'namenode_host');
     try {
-      nameNodeHost.defaultValue = hostComponents.filterProperty('componentName', 'NAMENODE').mapProperty('host.hostName');
-      globalConfigs.push(nameNodeHost);
+      this.setHostForService('HDFS', 'NAMENODE', 'namenode_host', true);
     } catch (err) {
       console.log("No NameNode Host available.  This is expected if you're using GLUSTERFS rather than HDFS.");
     }
 
-    //zooKeeperserver_host
-    var zooKeperHost = this.get('serviceConfigs').findProperty('serviceName', 'ZOOKEEPER').configs.findProperty('name', 'zookeeperserver_hosts');
-    if (serviceName === 'ZOOKEEPER' || serviceName === 'HBASE' || serviceName === 'WEBHCAT') {
-      zooKeperHost.defaultValue = hostComponents.filterProperty('componentName', 'ZOOKEEPER_SERVER').mapProperty('host.hostName');
-      globalConfigs.push(zooKeperHost);
-    }
-
-    switch (serviceName) {
-      case 'HDFS':
-        if (hostComponents.someProperty('componentName', 'SECONDARY_NAMENODE') && hostComponents.findProperty('componentName', 'SECONDARY_NAMENODE').get('workStatus') != 'DISABLED') {
-          var sNameNodeHost = serviceConfigs.findProperty('name', 'snamenode_host');
-          sNameNodeHost.defaultValue = hostComponents.findProperty('componentName', 'SECONDARY_NAMENODE').get('host.hostName');
-          globalConfigs.push(sNameNodeHost);
-        }
-        break;
-      case 'MAPREDUCE':
-        var jobTrackerHost = serviceConfigs.findProperty('name', 'jobtracker_host');
-        jobTrackerHost.defaultValue = hostComponents.findProperty('componentName', 'JOBTRACKER').get('host.hostName');
-        globalConfigs.push(jobTrackerHost);
-      case 'MAPREDUCE2':
-        var historyServerHost = serviceConfigs.findProperty('name', 'hs_host');
-        historyServerHost.defaultValue = hostComponents.findProperty('componentName', 'HISTORYSERVER').get('host.hostName');
-        globalConfigs.push(historyServerHost);
-        break;
-      case 'YARN':
-        var resourceManagerHost = serviceConfigs.findProperty('name', 'rm_host');
-        var ATSHost = this.getMasterComponentHostValue('APP_TIMELINE_SERVER');
-        if (ATSHost) {
-          var ATSProperty = serviceConfigs.findProperty('name', 'ats_host');
-          ATSProperty.defaultValue = ATSHost
-          globalConfigs.push(ATSProperty);
-        }
-        resourceManagerHost.defaultValue = hostComponents.findProperty('componentName', 'RESOURCEMANAGER').get('host.hostName');
-        globalConfigs.push(resourceManagerHost);
-        //yarn.log.server.url config dependent on HistoryServer host
-        if (hostComponents.someProperty('componentName', 'HISTORYSERVER')) {
-          historyServerHost = this.get('serviceConfigs').findProperty('serviceName', 'MAPREDUCE2').configs.findProperty('name', 'hs_host');
-          historyServerHost.defaultValue = hostComponents.findProperty('componentName', 'HISTORYSERVER').get('host.hostName');
-          globalConfigs.push(historyServerHost);
-        }
-        break;
-      case 'HIVE':
-        var hiveMetastoreHost = serviceConfigs.findProperty('name', 'hivemetastore_host');
-        hiveMetastoreHost.defaultValue = hostComponents.findProperty('componentName', 'HIVE_SERVER').get('host.hostName');
-        globalConfigs.push(hiveMetastoreHost);
-        var hiveDb = globalConfigs.findProperty('name', 'hive_database').value;
-        if (['Existing MySQL Database', 'Existing Oracle Database'].contains(hiveDb)) {
-          globalConfigs.findProperty('name', 'hive_hostname').isVisible = true;
-        }
-        break;
-
-      case 'OOZIE':
-        var oozieServerHost = serviceConfigs.findProperty('name', 'oozieserver_host');
-        oozieServerHost.defaultValue = hostComponents.findProperty('componentName', 'OOZIE_SERVER').get('host.hostName');
-        globalConfigs.push(oozieServerHost);
-        var oozieDb = globalConfigs.findProperty('name', 'oozie_database').value;
-        if (['Existing MySQL Database', 'Existing Oracle Database'].contains(oozieDb)) {
-          globalConfigs.findProperty('name', 'oozie_hostname').isVisible = true;
-        }
-        break;
-      case 'HBASE':
-        var hbaseMasterHost = serviceConfigs.findProperty('name', 'hbasemaster_host');
-        hbaseMasterHost.defaultValue = hostComponents.filterProperty('componentName', 'HBASE_MASTER').mapProperty('host.hostName');
-        globalConfigs.push(hbaseMasterHost);
-        break;
-      case 'HUE':
-        var hueServerHost = serviceConfigs.findProperty('name', 'hueserver_host');
-        hueServerHost.defaultValue = hostComponents.findProperty('componentName', 'HUE_SERVER').get('host.hostName');
-        globalConfigs.push(hueServerHost);
-        break;
-      case 'WEBHCAT':
-        var webhcatMasterHost = serviceConfigs.findProperty('name', 'webhcatserver_host');
-        webhcatMasterHost.defaultValue = hostComponents.filterProperty('componentName', 'WEBHCAT_SERVER').mapProperty('host.hostName');
-        globalConfigs.push(webhcatMasterHost);
-        var hiveMetastoreHost = this.get('serviceConfigs').findProperty('serviceName', 'HIVE').configs.findProperty('name', 'hivemetastore_host');
-        hiveMetastoreHost.defaultValue = hostComponents.findProperty('componentName', 'HIVE_SERVER').get('host.hostName');
-        globalConfigs.push(hiveMetastoreHost);
-        break;
-      case 'STORM':
-        var masterHostComponents = [
-          { name: 'STORM_UI_SERVER', propertyName: 'stormuiserver_host' },
-          { name: 'DRPC_SERVER', propertyName: 'drpcserver_host' },
-          { name: 'STORM_REST_API', propertyName: 'storm_rest_api_host' }
-        ];
-
-        masterHostComponents.forEach(function(component) {
-          var hostValue = this.getMasterComponentHostValue(component.name);
-          var config = serviceConfigs.findProperty('name', component.propertyName);
-          config.defaultValue = hostValue;
-          globalConfigs.push(config);
-        }, this);
+    var hostProperties = this.get('hostComponentsmapping').filter(function(h) {
+      return h.serviceUseThis.contains(serviceName) || h.serviceName == serviceName;
+    });
+    hostProperties.forEach(function(h) {
+      this.setHostForService(h.serviceName, h.componentName, h.hostProperty, h.m);
+    }, this);
 
-        var supervisorHosts = hostComponents.filterProperty('componentName','SUPERVISOR').mapProperty('host.hostName');
-        if (supervisorHosts.length > 0) {
-          var supervisorHostsConfig = serviceConfigs.findProperty('name', 'supervisor_hosts');
-          supervisorHostsConfig.defaultValue = supervisorHosts;
-          globalConfigs.push(supervisorHostsConfig);
-        }
-        break;
+    if (serviceName === 'HIVE') {
+      var hiveDb = globalConfigs.findProperty('name', 'hive_database').value;
+      if (['Existing MySQL Database', 'Existing Oracle Database'].contains(hiveDb)) {
+        globalConfigs.findProperty('name', 'hive_hostname').isVisible = true;
+      }
+    }
+    if (serviceName === 'OOZIE') {
+      var oozieDb = globalConfigs.findProperty('name', 'oozie_database').value;
+      if (['Existing MySQL Database', 'Existing Oracle Database'].contains(oozieDb)) {
+        globalConfigs.findProperty('name', 'oozie_hostname').isVisible = true;
+      }
+    }
+  },
+  /**
+   * set host name(s) property for component
+   * @param {String} serviceName - service name of component
+   * @param {String} componentName - component name whic host we want to know
+   * @param {String} hostProperty - name of host property for current component
+   * @param {Boolean} multiple - true if can be more than one component
+   * @method setHostForService
+   */
+  setHostForService: function(serviceName, componentName, hostProperty, multiple) {
+    var globalConfigs = this.get('globalConfigs');
+    var serviceConfigs = this.get('serviceConfigs').findProperty('serviceName', serviceName).configs;
+    var hostConfig = serviceConfigs.findProperty('name', hostProperty);
+    if (hostConfig) {
+      hostConfig.defaultValue = this.getMasterComponentHostValue(componentName, multiple);
+      globalConfigs.push(hostConfig);
     }
   },
 
   /**
    * get hostName of component
    * @param {String} componentName
-   * @return {String} hostName
+   * @param {Boolean} multiple - true if can be more than one component installed on cluster
+   * @return {String|Array|Boolean} hostName|hostNames|false if missing component
    * @method getMasterComponentHostValue
    */
-  getMasterComponentHostValue: function(componentName) {
-    var component = this.get('content.hostComponents').findProperty('componentName', componentName);
-    return component ? component.get('host.hostName') : false;
+  getMasterComponentHostValue: function(componentName, multiple) {
+    var components = this.get('content.hostComponents').filterProperty('componentName', componentName);
+    if (components.length > 0) {
+      return multiple ? components.mapProperty('host.hostName') : components[0].get('host.hostName');
+    }
+    return false;
   },
   /**
    * Provides service component name and display-name information for

http://git-wip-us.apache.org/repos/asf/ambari/blob/105b41b0/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 b701a05..746669e 100644
--- a/ambari-web/test/controllers/main/service/info/config_test.js
+++ b/ambari-web/test/controllers/main/service/info/config_test.js
@@ -435,26 +435,53 @@ describe("App.MainServiceInfoConfigsController", function () {
   });
 
   describe("#getMasterComponentHostValue", function () {
-    var t = Em.Object.create({
-      content: Em.Object.create({
-        hostComponents: [
-          Em.Object.create({
-            componentName: "componentName2",
-            displayName: "displayName2",
-            host: Em.Object.create({
-              hostName: "hostName"
+    var tests = [
+      {
+        content: {
+          hostComponents: [
+            Em.Object.create({
+              componentName: "componentName1",
+              host: {
+                hostName: "hostName"
+              }
             })
-          })
-        ]
-      })
-    });
-    beforeEach(function () {
-      mainServiceInfoConfigsController.set("content", { hostComponents: Em.A([])});
-    });
+          ]
+        },
+        result: "hostName",
+        multiple: false,
+        m: "returns hostname"
+      },
+      {
+        content: {
+          hostComponents: [
+            Em.Object.create({
+              componentName: "componentName2",
+              host: {
+                  hostName: "hostName1"
+              }
+            }),
+            Em.Object.create({
+              componentName: "componentName2",
+              host: {
+                hostName: "hostName2"
+              }
+            })
+          ]
+        },
+        result: ["hostName1","hostName2"],
+        multiple: true,
+        m: "returns hostnames"
+      }
+    ];
+    tests.forEach(function(t){
+      beforeEach(function () {
+        mainServiceInfoConfigsController.set("content", { hostComponents: []});
+      });
 
-    it("returns hostname", function () {
-      mainServiceInfoConfigsController.get("content.hostComponents").push(t.content.hostComponents[0]);
-      expect(mainServiceInfoConfigsController.getMasterComponentHostValue(t.content.hostComponents[0].componentName)).to.equal(t.content.hostComponents[0].host.hostName);
+      it(t.m, function () {
+        mainServiceInfoConfigsController.set("content.hostComponents", t.content.hostComponents);
+        expect(mainServiceInfoConfigsController.getMasterComponentHostValue(t.content.hostComponents[0].componentName, t.multiple)).to.eql(t.result);
+      });
     });
   });
 
@@ -705,4 +732,494 @@ describe("App.MainServiceInfoConfigsController", function () {
     });
   });
 
+  describe("#addDynamicProperties", function() {
+
+    var tests = [
+      {
+        stepConfigs: [Em.Object.create({
+          serviceName: "WEBHCAT",
+          configs: []
+        })],
+        content: Em.Object.create({
+          serviceName: "WEBHCAT"
+        }),
+        m: "add dynamic property",
+        addDynamic: true
+      },
+      {
+        stepConfigs: [Em.Object.create({
+          serviceName: "WEBHCAT",
+          configs: [
+            Em.Object.create({
+              name: "templeton.hive.properties"
+            })
+          ]
+        })],
+        content: Em.Object.create({
+          serviceName: "WEBHCAT"
+        }),
+        m: "don't add dynamic property (already included)",
+        addDynamic: false
+      },
+      {
+        stepConfigs: [Em.Object.create({
+          serviceName: "HDFS",
+          configs: []
+        })],
+        content: Em.Object.create({
+          serviceName: "HDFS"
+        }),
+        m: "don't add dynamic property (wrong service)",
+        addDynamic: false
+      }
+    ];
+    var dynamicProperty = {
+      "name": "templeton.hive.properties",
+      "templateName": ["hivemetastore_host"],
+      "foreignKey": null,
+      "value": "hive.metastore.local=false,hive.metastore.uris=thrift://<templateName[0]>:9083,hive.metastore.sasl.enabled=yes,hive.metastore.execute.setugi=true,hive.metastore.warehouse.dir=/apps/hive/warehouse",
+      "filename": "webhcat-site.xml"
+    };
+
+
+
+    tests.forEach(function(t) {
+      it(t.m, function() {
+        mainServiceInfoConfigsController.set("content", t.content);
+        mainServiceInfoConfigsController.set("stepConfigs", t.stepConfigs);
+        var configs = [];
+        mainServiceInfoConfigsController.addDynamicProperties(configs);
+        if (t.addDynamic){
+          expect(configs.findProperty("name","templeton.hive.properties")).to.deep.eql(dynamicProperty);
+        }
+      });
+    });
+  });
+
+  describe("#loadUiSideConfigs", function () {
+
+    var t = {
+      configMapping: [
+        {
+          foreignKey: null,
+          templateName: "",
+          value: "default",
+          name: "name1",
+          filename: "filename1"
+        },
+        {
+          foreignKey: "notNull",
+          templateName: "",
+          value: "default2",
+          name: "name2",
+          filename: "filename2"
+        }
+      ],
+      configMappingf: [
+        {
+          foreignKey: null,
+          templateName: "",
+          value: "default",
+          name: "name1",
+          filename: "filename1"
+        }
+      ],
+      valueWithOverrides: {
+        "value": "default",
+        "overrides": {
+          "value1": "value1",
+          "value2": "value2"
+        }
+      },
+      uiConfigs: [
+        {
+          "id": "site property",
+          "name": "name1",
+          "value": "default",
+          "filename": "filename1",
+          "overrides": {
+            "value1": "value1",
+            "value2": "value2"
+          }
+        }
+      ]
+    };
+
+    beforeEach(function(){
+      sinon.stub(mainServiceInfoConfigsController, "addDynamicProperties", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "getGlobConfigValueWithOverrides", function () {
+        return t.valueWithOverrides
+      });
+    });
+
+    afterEach(function(){
+      mainServiceInfoConfigsController.addDynamicProperties.restore();
+      mainServiceInfoConfigsController.getGlobConfigValueWithOverrides.restore();
+    });
+
+    it("load ui config", function() {
+      expect(mainServiceInfoConfigsController.loadUiSideConfigs(t.configMapping)[0]).to.deep.equal(t.uiConfigs[0]);
+      expect(mainServiceInfoConfigsController.addDynamicProperties.calledWith(t.configMappingf)).to.equal(true);
+    });
+  });
+
+  describe("#formatConfigValues", function () {
+    var t = {
+      configs: [
+        Em.Object.create({ name: "p1", value: " v1 v1 ", displayType: "" }),
+        Em.Object.create({ name: "p2", value: true, displayType: "" }),
+        Em.Object.create({ name: "p3", value: " d1 ", displayType: "directory" }),
+        Em.Object.create({ name: "p4", value: " d1 d2 d3 ", displayType: "directories" }),
+        Em.Object.create({ name: "p5", value: " v1 ", displayType: "password" }),
+        Em.Object.create({ name: "p6", value: " v ", displayType: "host" }),
+        Em.Object.create({ name: "javax.jdo.option.ConnectionURL", value: " v1 ", displayType: "advanced" }),
+        Em.Object.create({ name: "oozie.service.JPAService.jdbc.url", value: " v1 ", displayType: "advanced" })
+      ],
+      result: [
+        Em.Object.create({ name: "p1", value: " v1 v1", displayType: "" }),
+        Em.Object.create({ name: "p2", value: "true", displayType: "" }),
+        Em.Object.create({ name: "p3", value: "d1", displayType: "directory" }),
+        Em.Object.create({ name: "p4", value: "d1,d2,d3", displayType: "directories" }),
+        Em.Object.create({ name: "p5", value: " v1 ", displayType: "password" }),
+        Em.Object.create({ name: "p6", value: "v", displayType: "host" }),
+        Em.Object.create({ name: "javax.jdo.option.ConnectionURL", value: " v1", displayType: "advanced" }),
+        Em.Object.create({ name: "oozie.service.JPAService.jdbc.url", value: " v1", displayType: "advanced" })
+      ]
+    };
+
+    it("format config values", function () {
+      mainServiceInfoConfigsController.formatConfigValues(t.configs);
+      expect(t.configs).to.deep.equal(t.result);
+    });
+
+  });
+
+  describe("#setHostForService", function () {
+    var tests = [
+      {
+        globalConfigs: [],
+        componentName: "ZOOKEEPER_SERVER",
+        serviceName: "ZOOKEEPER",
+        hostProperty: "zookeeperserver_hosts",
+        multiple: true,
+        result: ["hostName1", "hostName2"],
+        serviceConfigs: [
+          {
+            serviceName: "ZOOKEEPER",
+            configs: [
+              {
+                "name": "zookeeperserver_hosts",
+                "defaultValue": null
+              }
+            ]
+          }
+        ],
+        m: "set hostNames to globalConfigs for current service"
+      },
+      {
+        globalConfigs: [],
+        componentName: "STORM_UI_SERVER",
+        serviceName: "STORM",
+        hostProperty: "stormuiserver_host",
+        multiple: false,
+        result: "hostName1",
+        serviceConfigs: [
+          {
+            serviceName: "STORM",
+            configs: [
+              {
+                "name": "stormuiserver_host",
+                "defaultValue": null
+              }
+            ]
+          }
+        ],
+        m: "set hostName to globalConfigs for current service"
+      }
+    ];
+
+    beforeEach(function () {
+      sinon.stub(mainServiceInfoConfigsController, "getMasterComponentHostValue", function (a,m) {
+        if (m) {
+          return ["hostName1", "hostName2"];
+        } else {
+          return "hostName1";
+        }
+      });
+    });
+
+    afterEach(function () {
+      mainServiceInfoConfigsController.getMasterComponentHostValue.restore();
+    });
+
+    tests.forEach(function (t) {
+      it(t.m, function () {
+        mainServiceInfoConfigsController.set("globalConfigs", t.globalConfigs);
+        mainServiceInfoConfigsController.set("serviceConfigs", t.serviceConfigs);
+        mainServiceInfoConfigsController.setHostForService(t.serviceName, t.componentName, t.hostProperty, t.multiple);
+        expect(mainServiceInfoConfigsController.get("globalConfigs").findProperty("name", t.hostProperty).defaultValue).to.eql(t.result);
+
+      });
+    }, this);
+  });
+
+  describe("#addHostNamesToGlobalConfig", function () {
+    var tests = [
+      {
+        globalConfigs: [],
+        serviceName: "ZOOKEEPER",
+        hostProperty: "zookeeperserver_hosts",
+        nameNodeHost: "namenode_host",
+        serviceConfigs: [
+          {
+            serviceName: "ZOOKEEPER",
+            configs: [
+              {
+                "name": "zookeeperserver_hosts",
+                "defaultValue": null
+              },
+              {
+                "name": "namenode_host",
+                "defaultValue": null
+              }
+            ]
+          }
+        ],
+        result: ["hostName1", "hostName2"],
+        result2: ["hostName1", "hostName2"],
+        m: "set hostNames to globalConfigs for required services"
+      },
+      {
+        globalConfigs: [
+          {
+            "name": "hive_database",
+            "value": "Existing MySQL Database"
+          },
+          {
+            "name": "hive_hostname",
+            "isVisible": false
+          }
+        ],
+        serviceName: "HIVE",
+        hostProperty: "hivemetastore_host",
+        nameNodeHost: "namenode_host",
+        isVisible: true,
+        serviceConfigs: [
+          {
+            serviceName: "HIVE",
+            configs: [
+              {
+                "name": "hivemetastore_host",
+                "defaultValue": null
+              },
+              {
+                "name": "namenode_host",
+                "defaultValue": null
+              }
+            ]
+          }
+        ],
+        result: "hostName3",
+        result2: ["hostName1", "hostName2"],
+        m: "set hostNames to globalConfigs for required services and isVisible property for HIVE"
+      }
+    ];
+
+    beforeEach(function () {
+      mainServiceInfoConfigsController.set("content", Em.Object.create({}));
+      sinon.stub(mainServiceInfoConfigsController, "getMasterComponentHostValue", function (a,m) {
+        if (m) {
+          return ["hostName1", "hostName2"];
+        } else {
+          return "hostName3";
+        }
+      });
+    });
+
+    afterEach(function () {
+      mainServiceInfoConfigsController.getMasterComponentHostValue.restore();
+    });
+
+    tests.forEach(function (t) {
+      it(t.m, function () {
+        mainServiceInfoConfigsController.set("content.serviceName", t.serviceName);
+        mainServiceInfoConfigsController.set("globalConfigs", t.globalConfigs);
+        mainServiceInfoConfigsController.set("serviceConfigs", t.serviceConfigs);
+        mainServiceInfoConfigsController.addHostNamesToGlobalConfig();
+        expect(mainServiceInfoConfigsController.get("globalConfigs").findProperty("name", t.hostProperty).defaultValue).to.eql(t.result);
+        expect(mainServiceInfoConfigsController.get("globalConfigs").findProperty("name", t.nameNodeHost).defaultValue).to.eql(t.result2);
+        if (t.serviceName == "HIVE" || t.serviceName == "OOZIE") {
+          expect(mainServiceInfoConfigsController.get("globalConfigs").findProperty("name", t.hostProperty).isVisible).to.eql(t.isVisible);
+        }
+      });
+    }, this);
+  });
+
+  describe("#doPUTClusterConfiguration", function () {
+    var tests = [
+      {
+        configs: {
+          properties: {
+            property1: "1001",
+            property2: "text"
+          }
+        },
+        siteName: "global",
+        r: true,
+        m: "save changed properties"
+      },
+      {
+        configs: {
+          properties: {
+            property1: "1000",
+            property2: "text"
+          }
+        },
+        siteName: "global",
+        r: true,
+        m: "skip saving becouse nothing changed (returns true)"
+      },
+      {
+        configs: {
+          properties: {
+            property1: "1001",
+            property2: "text"
+          },
+          success: false
+        },
+        siteName: "global",
+        r: false,
+        m: "saving failed"
+      }
+    ];
+    var getConfigsByTags = {
+      property1: "1000",
+      property2: "text"
+    }
+    beforeEach(function () {
+      sinon.stub(App.router.get('configurationController'), "getConfigsByTags", function () {
+        return getConfigsByTags
+      });
+      sinon.stub(mainServiceInfoConfigsController, "doPUTClusterConfigurationSite", function (k) {
+        return k.success !== false;
+      });
+    });
+
+    afterEach(function () {
+      mainServiceInfoConfigsController.doPUTClusterConfigurationSite.restore();
+      App.router.get('configurationController').getConfigsByTags.restore();
+    });
+    tests.forEach(function (t) {
+      it(t.m, function () {
+        var siteNameToServerDataMap = {};
+        expect(mainServiceInfoConfigsController.doPUTClusterConfiguration(siteNameToServerDataMap, t.siteName, t.configs)).to.equal(t.r);
+        expect(siteNameToServerDataMap[t.siteName]).to.eql(t.configs);
+      })
+    });
+  });
+
+  describe("#createConfigObject", function() {
+    var tests = [
+      {
+        siteName: "global",
+        method: "createGlobalSiteObj"
+      },
+      {
+        siteName: "core-site",
+        serviceName: "HDFS",
+        method: "createCoreSiteObj"
+      },
+      {
+        siteName: "core-site",
+        serviceName: "ANY",
+        method: false
+      },
+      {
+        siteName: "any",
+        method: "createSiteObj"
+      },
+      {
+        siteName: "mapred-queue-acls",
+        method: false,
+        capacitySchedulerUi: false
+      },
+      {
+        siteName: "mapred-queue-acls",
+        method: "createSiteObj",
+        capacitySchedulerUi: true
+      }
+    ];
+
+    var capacitySchedulerUi = App.supports.capacitySchedulerUi;
+    beforeEach(function() {
+      sinon.stub(mainServiceInfoConfigsController, "createGlobalSiteObj", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "createCoreSiteObj", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "createSiteObj", Em.K);
+      mainServiceInfoConfigsController.set("content", {});
+    });
+
+    afterEach(function() {
+      mainServiceInfoConfigsController.createGlobalSiteObj.restore();
+      mainServiceInfoConfigsController.createCoreSiteObj.restore();
+      mainServiceInfoConfigsController.createSiteObj.restore();
+      App.supports.capacitySchedulerUi = capacitySchedulerUi;
+    });
+
+    tests.forEach(function(t) {
+      it("create object for " + t.siteName + " run method " + t.method, function() {
+        App.supports.capacitySchedulerUi = t.capacitySchedulerUi;
+        mainServiceInfoConfigsController.set("content.serviceName", t.serviceName);
+        mainServiceInfoConfigsController.createConfigObject(t.siteName, "versrion1");
+        if (t.method) {
+          expect(mainServiceInfoConfigsController[t.method].calledOnce).to.equal(true);
+        } else {
+          expect(mainServiceInfoConfigsController["createGlobalSiteObj"].calledOnce).to.equal(false);
+          expect(mainServiceInfoConfigsController["createCoreSiteObj"].calledOnce).to.equal(false);
+          expect(mainServiceInfoConfigsController["createSiteObj"].calledOnce).to.equal(false);
+        }
+      });
+    });
+  });
+
+  describe("#doPUTClusterConfigurations", function() {
+
+    var t = {
+     propertyName: "global",
+     properties: {
+       propertu1: "text",
+       property2: 1000
+     },
+     serviceConfigTags: [{
+       siteName: "global",
+       tagName: "version1"
+     }]
+    };
+
+    beforeEach(function() {
+      sinon.stub(mainServiceInfoConfigsController, "createConfigObject", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "setNewTagNames", Em.K);
+      sinon.stub(mainServiceInfoConfigsController, "doPUTClusterConfiguration", function (siteNameToServerDataMap) {
+        siteNameToServerDataMap[t.propertyName] = t.properties;
+        return true;
+      });
+    });
+
+    afterEach(function() {
+      mainServiceInfoConfigsController.createConfigObject.restore();
+      mainServiceInfoConfigsController.setNewTagNames.restore();
+      mainServiceInfoConfigsController.doPUTClusterConfiguration.restore();
+    });
+
+    it("Saves cluster level configurations", function() {
+      var siteNameToServerDataMap = {};
+      siteNameToServerDataMap[t.propertyName] = t.properties;
+      mainServiceInfoConfigsController.set("serviceConfigTags", t.serviceConfigTags);
+      expect(mainServiceInfoConfigsController.doPUTClusterConfigurations()).to.equal(true);
+      expect(mainServiceInfoConfigsController["createConfigObject"].calledOnce).to.equal(true);
+      expect(mainServiceInfoConfigsController["setNewTagNames"].calledOnce).to.equal(true);
+      expect(mainServiceInfoConfigsController["doPUTClusterConfiguration"].calledOnce).to.equal(true);
+      expect(mainServiceInfoConfigsController.get("savedSiteNameToServerServiceConfigDataMap")).to.eql(siteNameToServerDataMap);
+    });
+
+  });
 });