You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mr...@apache.org on 2017/11/27 23:29:34 UTC

[22/30] ambari git commit: Merge trunk with feature branch and fix some UT compilation issues (mradhakrishnan)

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/CreateViewInstanceCtrl.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/CreateViewInstanceCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/CreateViewInstanceCtrl.js
deleted file mode 100644
index f8ccc24..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/CreateViewInstanceCtrl.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-describe('#CreateViewInstanceCtrl', function () {
-  var scope, ctrl, $httpBackend, View;
-
-  beforeEach(module('ambariAdminConsole', function($provide){
-    $provide.value('$routeParams', {viewId: 'TestView'});
-  }));
-
-  afterEach(function() {
-    $httpBackend.verifyNoOutstandingExpectation();
-    $httpBackend.verifyNoOutstandingRequest();
-  });
-
-  beforeEach(inject(function (_$httpBackend_, $rootScope, $controller, _View_, $q) {
-    View = _View_;
-    spyOn(View, 'createInstance').andReturn($q.defer().promise);
-    spyOn(View, 'getInstance').andReturn($q.defer().promise);
-
-    $httpBackend = _$httpBackend_;
-    $httpBackend.whenGET(/\/api\/v1\/views\/TestView\?.+/).respond(200, {
-      "versions": [{"ViewVersionInfo": {}}]
-    });
-    $httpBackend.whenGET(/\/api\/v1\/views\/TestView\/versions\/1\.0\.0/).respond(200, {
-      "ViewVersionInfo": {"parameters": [{"name": "n", "defaultValue": "d"}]}
-    });
-    $httpBackend.whenGET('template/modal/backdrop.html').respond(200, '<div></div>');
-    $httpBackend.whenGET('template/modal/window.html').respond(200, '<div></div>');
-    scope = $rootScope.$new();
-    ctrl = $controller('CreateViewInstanceCtrl', {$scope: scope});
-  }));
-
-  it('it should invoke View.createInstance on save', function () {
-    scope.form = {
-      instanceCreateForm: {
-        submitted: false,
-        $valid: true
-      }
-    };
-    $httpBackend.flush();
-    scope.instance = {};
-    scope.save();
-    expect(View.createInstance).toHaveBeenCalled();
-  });
-
-  it('should set default property value before creating view instance', function () {
-    scope.form = {
-      instanceCreateForm: {
-        $dirty: true
-      }
-    };
-    scope.instance = {};
-    scope.version = '1.0.0';
-    scope.isClone=false;
-    $httpBackend.expectGET('template/modal/backdrop.html');
-    $httpBackend.expectGET('template/modal/window.html');
-    $httpBackend.whenGET(/\/api\/v1\/clusters\?fields=Clusters\/cluster_id&_=\d+/).respond(200, {
-      "items" : [
-        {
-          "Clusters" : {
-            "cluster_name" : "c1",
-            "version" : "HDP-2.2"
-          }
-        }
-      ]
-    });
-    $httpBackend.whenGET(/\/api\/v1\/remoteclusters\?fields=ClusterInfo\/services,ClusterInfo\/cluster_id&_=\d+/).respond(200, {
-      "items" : [
-         {
-           "ClusterInfo" : {
-            "name" : "c1",
-            "services" : ["HDFS"]
-          }
-        }
-      ]
-    });
-    scope.$digest();
-    $httpBackend.flush();
-    chai.expect(scope.view.ViewVersionInfo.parameters[0].value).to.equal('d');
-    expect(View.getInstance).not.toHaveBeenCalled();
-  });
-
-  it('before cloning view instance confirm that View.getInstance is called', function () {
-    scope.form = {
-      instanceCreateForm: {
-        $dirty: true
-      }
-    };
-    scope.instance = {};
-    scope.version = '1.0.0';
-    scope.isClone=true;
-    $httpBackend.expectGET('template/modal/backdrop.html');
-    $httpBackend.expectGET('template/modal/window.html');
-    $httpBackend.whenGET(/\/api\/v1\/clusters\?fields=Clusters\/cluster_id&_=\d+/).respond(200, {
-      "items" : [
-        {
-          "Clusters" : {
-            "cluster_name" : "c1",
-            "version" : "HDP-2.2"
-          }
-        }
-      ]
-    });
-    $httpBackend.whenGET(/\/api\/v1\/remoteclusters\?fields=ClusterInfo\/services,ClusterInfo\/cluster_id&_=\d+/).respond(200, {
-      "items" : [
-         {
-           "ClusterInfo" : {
-            "name" : "c1",
-            "services" : ["HDFS"]
-          }
-        }
-      ]
-    });
-    scope.$digest();
-    $httpBackend.flush();
-    expect(View.getInstance).toHaveBeenCalled(); 
-  });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
deleted file mode 100644
index 14c0975..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/clusters/UserAccessListCtrl_test.js
+++ /dev/null
@@ -1,820 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-describe('#Cluster', function () {
-
-  describe('UserAccessListCtrl', function() {
-
-    var scope, ctrl, $t, $httpBackend, Cluster, deferred, Alert, mock;
-
-    beforeEach(module('ambariAdminConsole', function () {}));
-
-    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_, _Cluster_, _$q_, _Alert_) {
-      scope = $rootScope.$new();
-      $t = _$translate_.instant;
-      $httpBackend = _$httpBackend_;
-      Cluster = _Cluster_;
-      Alert = _Alert_;
-      deferred = {
-        createPrivileges: _$q_.defer(),
-        getPrivilegesForResource: _$q_.defer(),
-        getPrivilegesWithFilters: _$q_.defer(),
-        deletePrivileges: _$q_.defer(),
-        deleteMultiplePrivileges: _$q_.defer()
-      };
-      ctrl = $controller('UserAccessListCtrl', {
-        $scope: scope
-      });
-      mock = {
-        Cluster: Cluster,
-        Alert: Alert,
-        scope: scope
-      };
-      spyOn(Cluster, 'createPrivileges').andReturn(deferred.createPrivileges.promise);
-      spyOn(Cluster, 'deletePrivileges').andReturn(deferred.deletePrivileges.promise);
-      spyOn(Cluster, 'getPrivilegesForResource').andReturn(deferred.getPrivilegesForResource.promise);
-      spyOn(Cluster, 'getPrivilegesWithFilters').andReturn(deferred.getPrivilegesWithFilters.promise);
-      spyOn(Alert, 'success').andCallFake(angular.noop);
-      spyOn(Alert, 'error').andCallFake(angular.noop);
-      spyOn(scope, 'loadRoles').andCallFake(angular.noop);
-
-      $httpBackend.expectGET(/\/api\/v1\/permissions/).respond(200, {
-        items: []
-      });
-      $httpBackend.expectGET(/\/api\/v1\/users?.*/).respond(200, {
-        items:[]
-      });
-      $httpBackend.flush();
-    }));
-
-    describe('#clearFilters()', function () {
-
-      it('should clear filters and reset pagination', function () {
-        scope.currentPage = 2;
-        scope.currentNameFilter = 'a';
-        scope.roleFilterOptions = [
-          {
-            label: $t('common.all'),
-            value: ''
-          },
-          {
-            label: $t('users.roles.clusterUser'),
-            value: 'CLUSTER.USER'
-          }
-        ];
-        scope.currentRoleFilter = scope.roleFilterOptions[1];
-        scope.clearFilters();
-        expect(scope.currentNameFilter).toEqual('');
-        expect(scope.currentRoleFilter).toEqual({
-          label: $t('common.all'),
-          value: ''
-        });
-        expect(scope.currentPage).toEqual(1);
-      });
-
-    });
-
-    describe('#isNotEmptyFilter', function () {
-
-      var cases = [
-        {
-          currentNameFilter: '',
-          currentRoleFilter: null,
-          isNotEmptyFilter: false,
-          title: 'no filters'
-        },
-        {
-          currentNameFilter: '',
-          currentRoleFilter: {
-            value: ''
-          },
-          isNotEmptyFilter: false,
-          title: 'empty filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentRoleFilter: {
-            value: ''
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter'
-        },
-        {
-          currentNameFilter: '0',
-          currentRoleFilter: {
-            value: ''
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentRoleFilter: {
-            value: 'CLUSTER.USER'
-          },
-          isNotEmptyFilter: true,
-          title: 'role filter'
-        },
-        {
-          currentNameFilter: 'a',
-          currentRoleFilter: {
-            value: 'GROUP'
-          },
-          isNotEmptyFilter: true,
-          title: 'all filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentRoleFilter: {
-            value: 'GROUP'
-          },
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string'
-        }
-      ];
-
-      cases.forEach(function (item) {
-        it(item.title, function () {
-          scope.currentNameFilter = item.currentNameFilter;
-          scope.currentRoleFilter = item.currentRoleFilter;
-          scope.$digest();
-          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
-        });
-      });
-
-    });
-
-    describe('#save() for Users', function(){
-      var user = {};
-
-      beforeEach(function() {
-        items1 = {
-            "href" : "http://abc.com:8080/api/v1/users/user1",
-            "Users" : { "user_name" : "user1" },
-            "privileges" : [
-              {
-                "href" : "http://abc.com:8080/api/v1/users/user1/privileges/222",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "mygroup2",
-                  "principal_type" : "GROUP",
-                  "privilege_id" : 222,
-                  "type" : "CLUSTER",
-                  "user_name" : "user1"
-                }
-              }, {
-                "href" : "http://abc.com:8080/api/v1/users/user1/privileges/111",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "mygroup",
-                  "principal_type" : "GROUP",
-                  "privilege_id" : 111,
-                  "type" : "CLUSTER",
-                  "user_name" : "user1"
-                }
-              }, {
-                "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Cluster Administrator",
-                  "permission_name" : "CLUSTER.ADMINISTRATOR",
-                  "principal_name" : "user1",
-                  "principal_type" : "USER",
-                  "privilege_id" : 11,
-                  "type" : "CLUSTER",
-                  "user_name" : "user1"
-                }
-              }
-            ]
-          };
-
-        items2 =
-          {
-            "href" : "http://abc.com:8080/api/v1/users/user2",
-            "Users" : { "user_name" : "user2" },
-            "privileges" : [
-              {
-                "href" : "http://abc.com:8080/api/v1/users/user2/privileges/111",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "mygroup",
-                  "principal_type" : "GROUP",
-                  "privilege_id" : 111,
-                  "type" : "CLUSTER",
-                  "user_name" : "user2"
-                }
-              }, {
-                "href" : "http://abc.com:8080/api/v1/users/user2/privileges/22",
-                "PrivilegeInfo" : {
-                  "cluster_name" : "myCluster",
-                  "permission_label" : "Service Administrator",
-                  "permission_name" : "SERVICE.ADMINISTRATOR",
-                  "principal_name" : "user2",
-                  "principal_type" : "USER",
-                  "privilege_id" : 22,
-                  "type" : "CLUSTER",
-                  "user_name" : "user2"
-                }
-              }
-            ]
-          };
-
-        all_items = { "items": [items1, items2]};
-
-        scope.loadUsers();
-
-        spyOn(Cluster, 'deleteMultiplePrivileges').andCallFake(function(clusterId, privilege_ids) {
-          privilege_ids.forEach(function(privilege_id) {
-            items1.privileges.forEach(function(p, index) {
-              if (p.PrivilegeInfo.privilege_id === privilege_id) {
-                //Remove from array
-                items1.privileges.splice(index, 1);
-              }
-            });
-          });
-        });
-        spyOn(scope, 'addPrivilege').andCallFake(function(user) {
-          var p = {};
-          p.PrivilegeInfo = {};
-          p.PrivilegeInfo.privilege_id = user.privilege_id + 1;
-          p.PrivilegeInfo.permission_name = user.permission_name;
-          p.PrivilegeInfo.principal_type = 'USER';
-
-          items1.privileges.push(p);
-          scope.loadUsers();
-        });
-
-        deferred.getPrivilegesWithFilters.resolve(all_items);
-        deferred.getPrivilegesForResource.promise.then(function(data) {
-          var arrayOfPrivileges = data.items[0].privileges;
-          var privilegesOfTypeUser = [];
-          var privilegesOfTypeGroup = [];
-          for (var i = 0; i < arrayOfPrivileges.length; i++) {
-            if(arrayOfPrivileges[i].PrivilegeInfo.principal_type === "GROUP"){
-              privilegesOfTypeGroup.push(arrayOfPrivileges[i]);
-            } else {
-              privilegesOfTypeUser.push(arrayOfPrivileges[i].PrivilegeInfo);
-            }
-          }
-
-          var effectivePrivilege = scope.pickEffectivePrivilege(arrayOfPrivileges);
-          var effectivePrivilegeFromGroups = scope.pickEffectivePrivilege(privilegesOfTypeGroup);
-          user.principal_type = 'USER';
-          user.original_perm = effectivePrivilege.permission_name;
-          user.editable = (Cluster.ineditableRoles.indexOf(effectivePrivilege.permission_name) === -1);
-
-          //add a new privilege of type USER only if it is also the effective privilege considering the user's Group privileges
-          var curIndex = scope.getRoleRank(user.permission_name);
-          var prevIndex = -1;
-          if (privilegesOfTypeGroup.length !== 0) {
-            prevIndex = scope.getRoleRank(effectivePrivilegeFromGroups.permission_name);
-          }
-          if ((curIndex === 6) || (curIndex <= prevIndex)) {
-            var privilege_ids = [];
-            privilegesOfTypeUser.forEach(function(privilegeOfTypeUser) {
-              privilege_ids.push(privilegeOfTypeUser.privilege_id);
-            });
-
-            //delete all privileges of type USER, if they exist
-            //then add the privilege for the user, after which the user displays the effective privilege
-            if(privilege_ids.length !== 0) {
-              Cluster.deleteMultiplePrivileges(
-                123,
-                privilege_ids
-              );
-            }
-            scope.addPrivilege(user);
-          } else {
-            Alert.error($t('common.alerts.cannotSavePermissions'), "User's effective privilege through its Group(s) is higher than your selected privilege.");
-            scope.loadUsers();
-          }
-        });
-
-        scope.$apply();
-      });
-
-      it('Should save the Privilege equal to the user\'s group privileges. Should also remove any individual user privileges', function() {
-        //using 'user1' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "SERVICE.ADMINISTRATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "permission_label" : "Cluster Administrator",
-            "permission_name" : "CLUSTER.ADMINISTRATOR",
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : 11,
-            "type" : "CLUSTER",
-            "user_name" : "user1"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "permission_name" : user.permission_name,
-            "privilege_id" : user.privilege_id+1,
-            "principal_type" : "USER",
-            "principal_name" : "user1",
-            "encoded_name" : "user1",
-            "original_perm" : user.permission_name,
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-
-        //test if the individual user privilege CLUSTER.ADMINISTRATOR is removed from 'items1' by deletePrivilege()
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege got added to 'items1' by addPrivilege()
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should save the Privilege greater than the user\'s group privileges. Should also remove any individual user privileges', function() {
-        //using 'user1' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.OPERATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "permission_label" : "Cluster Administrator",
-            "permission_name" : "CLUSTER.ADMINISTRATOR",
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : 11,
-            "type" : "CLUSTER",
-            "user_name" : "user1"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "permission_name" : user.permission_name,
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : user.privilege_id + 1,
-            "encoded_name" : "user1",
-            "original_perm" : user.permission_name,
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-
-        //test if the individual user privilege CLUSTER.ADMINISTRATOR is removed from 'items1' by deletePrivilege()
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege got added to 'items1' by addPrivilege()
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should NOT save the Privilege smaller than the user\'s group privileges. Should keep the user\'s original privileges intact', function() {
-        //using 'user1' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.USER";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.original_perm);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id);
-
-        var oldPrivilege = {
-          "href" : "http://abc.com:8080/api/v1/users/user1/privileges/11",
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "permission_label" : "Cluster Administrator",
-            "permission_name" : "CLUSTER.ADMINISTRATOR",
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : 11,
-            "type" : "CLUSTER",
-            "user_name" : "user1",
-            "encoded_name" : "user1",
-            "original_perm" : "CLUSTER.ADMINISTRATOR",
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "permission_name" : user.permission_name,
-            "principal_name" : "user1",
-            "principal_type" : "USER",
-            "privilege_id" : user.privilege_id+1,
-            "encoded_name" : "user1",
-            "original_perm" : user.permission_name,
-            "url" : "users/user1",
-            "editable" : true
-          }
-        };
-
-        //test if the individual user privilege CLUSTER.ADMINISTRATOR is NOT removed from 'items1'
-        expect(items1.privileges).toContain(oldPrivilege);
-
-        //test if the new privilege is NOT added to 'items1'
-        expect(items1.privileges).toNotContain(newPrivilege);
-      });
-
-    });
-
-    describe('#save() for Groups', function() {
-      var user = {};
-
-      beforeEach(function() {
-        items1 = {
-          "href" : "http://abc.com:8080/api/v1/groups/mygroup",
-          "Groups" : { "group_name" : "mygroup" },
-          "privileges" : [
-            {
-              "href" : "http://abc.com:8080/api/v1/groups/mygroup/privileges/3359",
-              "PrivilegeInfo" : {
-                "cluster_name" : "myCluster",
-                "group_name" : "mygroup",
-                "permission_label" : "Service Administrator",
-                "permission_name" : "SERVICE.ADMINISTRATOR",
-                "principal_name" : "mygroup",
-                "principal_type" : "GROUP",
-                "privilege_id" : 3359,
-                "type" : "CLUSTER"
-              }
-            }
-          ]
-        };
-
-        items2 = {
-          "href" : "http://abc.com:8080/api/v1/groups/mygroup2",
-          "Groups" : { "group_name" : "mygroup2" },
-          "privileges" : [
-            {
-              "href" : "http://abc.com:8080/api/v1/groups/mygroup2/privileges/3356",
-              "PrivilegeInfo" : {
-                "cluster_name" : "myCluster",
-                "group_name" : "mygroup2",
-                "permission_label" : "Service Administrator",
-                "permission_name" : "SERVICE.ADMINISTRATOR",
-                "principal_name" : "mygroup2",
-                "principal_type" : "GROUP",
-                "privilege_id" : 3356,
-                "type" : "CLUSTER"
-              }
-            }
-          ]
-        };
-
-        all_items = { "items": [items1, items2]};
-
-        scope.loadUsers();
-
-        spyOn(Cluster, 'deleteMultiplePrivileges').andCallFake(function(clusterId, privilege_ids) {
-          privilege_ids.forEach(function(privilege_id) {
-            items1.privileges.forEach(function(p, index) {
-              if (p.PrivilegeInfo.privilege_id === privilege_id) {
-                //Remove from array
-                items1.privileges.splice(index, 1);
-              }
-            });
-          });
-        });
-        spyOn(scope, 'addPrivilege').andCallFake(function(user) {
-          var p = {};
-          p.PrivilegeInfo = {};
-          p.PrivilegeInfo.privilege_id = user.privilege_id + 1;
-          p.PrivilegeInfo.permission_name = user.permission_name;
-          p.PrivilegeInfo.principal_type = 'GROUP';
-
-          items1.privileges.push(p);
-          scope.loadUsers();
-        });
-
-        deferred.getPrivilegesWithFilters.resolve(all_items);
-        deferred.getPrivilegesForResource.promise.then(function(data) {
-          var arrayOfPrivileges = data.items[0].privileges;
-          var privilegesOfTypeGroup = [];
-          var privilege = scope.pickEffectivePrivilege(arrayOfPrivileges);
-          user.principal_type = 'GROUP';
-          user.original_perm = privilege.permission_name;
-          user.editable = (Cluster.ineditableRoles.indexOf(privilege.permission_name) === -1);
-
-          arrayOfPrivileges.forEach(function(privilegeOfTypeGroup){
-            if (privilegeOfTypeGroup.PrivilegeInfo.principal_type === "GROUP") {
-              privilegesOfTypeGroup.push(privilegeOfTypeGroup.PrivilegeInfo);
-            }
-          });
-
-          var privilege_ids = [];
-          privilegesOfTypeGroup.forEach(function(privilegeOfTypeGroup) {
-            privilege_ids.push(privilegeOfTypeGroup.privilege_id);
-          });
-
-          //delete all privileges of type GROUP, if they exist
-          //then add the privilege for the group, after which the group displays the effective privilege
-          if(privilege_ids.length !== 0) {
-            Cluster.deleteMultiplePrivileges(
-                123,
-                privilege_ids
-            );
-          }
-          scope.addPrivilege(user);
-        });
-
-        scope.$apply();
-      });
-
-      it('Should save the Privilege equal to the group\'s effective privilege. Should remove any other privileges of the group',function(){
-        //using 'mygroup' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "SERVICE.ADMINISTRATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "group_name" : "mygroup",
-            "permission_label" : "Service Administrator",
-            "permission_name" : "SERVICE.ADMINISTRATOR",
-            "principal_name" : "mygroup",
-            "principal_type" : "GROUP",
-            "privilege_id" : 3359,
-            "type" : "CLUSTER"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "privilege_id" : user.privilege_id + 1,
-            "permission_name" : user.permission_name,
-            "principal_type" : "GROUP",
-            "principal_name" : "mygroup",
-            "encoded_name" : "mygroup",
-            "original_perm" : user.permission_name,
-            "url" : "groups/mygroup/edit",
-            "editable" : true
-          }
-        };
-
-        //test if the older privilege is no longer present in 'items1'
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege is added to 'items1'
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should save the Privilege greater than the group\'s effective privilege. Should remove any other privileges of the group',function(){
-        //using 'mygroup' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.ADMINISTRATOR";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "group_name" : "mygroup",
-            "permission_label" : "Service Administrator",
-            "permission_name" : "SERVICE.ADMINISTRATOR",
-            "principal_name" : "mygroup",
-            "principal_type" : "GROUP",
-            "privilege_id" : 3359,
-            "type" : "CLUSTER"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "privilege_id" : user.privilege_id + 1,
-            "permission_name" : user.permission_name,
-            "principal_type" : "GROUP",
-            "principal_name" : "mygroup",
-            "encoded_name" : "mygroup",
-            "original_perm" : user.permission_name,
-            "url" : "groups/mygroup/edit",
-            "editable" : true
-          }
-        };
-
-        //test if the older privilege is no longer present in 'items1'
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege is added to 'items1'
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-      it('Should save the Privilege lesser than the group\'s effective privilege. Should remove any other privileges of the group', function() {
-        //using 'mygroup' for updating the new privilege
-        user.principal_name = scope.users[0].principal_name;
-        user.principal_type = scope.users[0].principal_type;
-        user.privilege_id = scope.users[0].privilege_id;
-        user.permission_name = "CLUSTER.USER";
-
-        deferred.getPrivilegesForResource.resolve({ "items" : [items1] });
-
-        scope.$apply();
-
-        expect(scope.users[0].permission_name).toEqual(user.permission_name);
-        expect(scope.users[0].privilege_id).toEqual(user.privilege_id + 1);
-
-        var oldPrivilege = {
-          "PrivilegeInfo" : {
-            "cluster_name" : "myCluster",
-            "group_name" : "mygroup",
-            "permission_label" : "Service Administrator",
-            "permission_name" : "SERVICE.ADMINISTRATOR",
-            "principal_name" : "mygroup",
-            "principal_type" : "GROUP",
-            "privilege_id" : 3359,
-            "type" : "CLUSTER"
-          }
-        };
-        var newPrivilege = {
-          "PrivilegeInfo" : {
-            "privilege_id" : user.privilege_id + 1,
-            "permission_name" : user.permission_name,
-            "principal_type" : "GROUP",
-            "principal_name" : "mygroup",
-            "encoded_name" : "mygroup",
-            "original_perm" : user.permission_name,
-            "url" : "groups/mygroup/edit",
-            "editable" : true
-          }
-        };
-
-        //test if the older privilege is no longer present in 'items1'
-        expect(items1.privileges).toNotContain(oldPrivilege);
-
-        //test if the new privilege is added to 'items1'
-        expect(items1.privileges).toContain(newPrivilege);
-      });
-
-    });
-
-    describe('#pickEffectivePrivilege()', function() {
-      var cases = [{
-          "test" : [{
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup1",
-            "PrivilegeInfo" : {
-              "instance_name" : "jobs_view",
-              "permission_label" : "View User",
-              "permission_name" : "VIEW.USER",
-              "principal_name" : "mygroup1",
-              "principal_type" : "GROUP",
-              "privilege_id" : 111,
-              "type" : "VIEW",
-              "user_name" : "mygroup1",
-              "view_name" : "JOBS"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.NONE"
-          }
-        }, {
-          "test": [{
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup2",
-            "PrivilegeInfo" : {
-              "cluster_name":"mycluster",
-              "permission_label" : "Cluster User",
-              "permission_name" : "CLUSTER.USER",
-              "principal_name" : "mygroup2",
-              "principal_type" : "GROUP",
-              "privilege_id" : 222,
-              "type" : "CLUSTER",
-              "user_name":"mygroup2"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.USER"
-          }
-        }, {
-          "test":[{
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup3",
-            "PrivilegeInfo" : {
-              "cluster_name":"mycluster",
-              "permission_label" : "Cluster User",
-              "permission_name" : "CLUSTER.USER",
-              "principal_name" : "mygroup3",
-              "principal_type" : "GROUP",
-              "privilege_id" : 333,
-              "type" : "CLUSTER",
-              "user_name":"mygroup3"
-            }
-          }, {
-            "href" : "http://abc.com:8080/api/v1/groups/mygroup3",
-            "PrivilegeInfo" : {
-              "instance_name": "jobs_view",
-              "permission_label" : "View User",
-              "permission_name" : "VIEW.USER",
-              "principal_name" : "mygroup3",
-              "principal_type" : "GROUP",
-              "privilege_id" : 3333,
-              "type" : "VIEW",
-              "user_name":"mygroup3",
-              "view_name":"JOBS"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.USER"
-          }
-        }, {
-          "test": [{
-            "href" : "http://abc.com:8080/api/v1/users/myuser1/privileges/11",
-            "PrivilegeInfo" : {
-              "instance_name": "jobs_view",
-              "permission_label" : "View User",
-              "permission_name" : "VIEW.USER",
-              "principal_name" : "myuser1",
-              "principal_type" : "USER",
-              "privilege_id" : 11,
-              "type" : "VIEW",
-              "user_name":"myuser1",
-              "view_name":"JOBS"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.NONE"
-          }
-        }, {
-          "test":[{
-            "href" : "http://abc.com:8080/api/v1/users/myuser2/privileges/22",
-            "PrivilegeInfo" : {
-              "cluster_name":"mycluster",
-              "permission_label" : "Cluster Administrator",
-              "permission_name" : "CLUSTER.ADMINISTRATOR",
-              "principal_name" : "myuser2",
-              "principal_type" : "USER",
-              "privilege_id" : 22,
-              "type" : "CLUSTER",
-              "user_name":"myuser2"
-            }
-          }],
-          "result":{
-            "permission_name": "CLUSTER.ADMINISTRATOR"
-          }
-        }
-      ];
-
-      it('User/Group with only View User permission must show \'None\' as the Cluster Permission, otherwise show the effective privilege', function(){
-        var effectivePrivilege;
-        cases.forEach(function (item){
-          effectivePrivilege = scope.pickEffectivePrivilege(item.test);
-          scope.$apply();
-          expect(effectivePrivilege.permission_name).toEqual(item.result.permission_name);
-        });
-      });
-    });
-
-  });
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
deleted file mode 100644
index 8ed228b..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/groups/GroupsListCtrl_test.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-describe('#Cluster', function () {
-
-  describe('GroupsListCtrl', function() {
-
-    var scope, ctrl, $t, $httpBackend;
-
-    beforeEach(module('ambariAdminConsole', function () {}));
-
-    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
-      scope = $rootScope.$new();
-      $t = _$translate_.instant;
-      $httpBackend = _$httpBackend_;
-      ctrl = $controller('GroupsListCtrl', {
-        $scope: scope
-      });
-    }));
-
-    describe('#clearFilters()', function () {
-
-      it('should clear filters and reset pagination', function () {
-        scope.currentPage = 2;
-        scope.currentNameFilter = 'a';
-        scope.currentTypeFilter = {
-          label: $t('common.local'),
-          value: false
-        };
-        scope.clearFilters();
-        expect(scope.currentNameFilter).toEqual('');
-        expect(scope.currentTypeFilter).toEqual({
-          label: $t('common.all'),
-          value: '*'
-        });
-        expect(scope.currentPage).toEqual(1);
-      });
-
-    });
-
-    describe('#isNotEmptyFilter', function () {
-
-      var cases = [
-        {
-          currentNameFilter: '',
-          currentTypeFilter: null,
-          isNotEmptyFilter: false,
-          title: 'no filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          isNotEmptyFilter: false,
-          title: 'empty filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          isNotEmptyFilter: true,
-          title: 'name filter with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: false
-          },
-          isNotEmptyFilter: true,
-          title: 'type filter'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: false
-          },
-          isNotEmptyFilter: true,
-          title: 'both filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: false
-          },
-          isNotEmptyFilter: true,
-          title: 'both filters with "0" as string'
-        }
-      ];
-
-      cases.forEach(function (item) {
-        it(item.title, function () {
-          $httpBackend.expectGET(/\/api\/v1\/groups/).respond(200);
-          scope.currentNameFilter = item.currentNameFilter;
-          scope.currentTypeFilter = item.currentTypeFilter;
-          scope.$digest();
-          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
-        });
-      });
-
-    });
-
-  });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/mainCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/mainCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/mainCtrl_test.js
deleted file mode 100644
index f03dcb5..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/mainCtrl_test.js
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-describe('#MainCtrl', function () {
-
-  var scope, ctrl, $httpBackend, $window, clusterService, deferred;
-
-  beforeEach(function () {
-    module('ambariAdminConsole', function ($provide) {
-      $provide.value('$window', {
-        location: {
-          pathname: 'http://c6401.ambari.apache.org:8080/views/ADMIN_VIEW/2.0.0/INSTANCE/#/'
-        },
-        localStorage: {
-          getItem: function () {
-            return null;
-          },
-          setItem: angular.noop
-        }
-      });
-      localStorage.ambari = JSON.stringify({
-        app: {
-          authenticated: true,
-          loginName: 'admin',
-          user: 'user'
-        }
-      });
-    });
-    inject(function (_$httpBackend_, $rootScope, $controller, _$window_, _Cluster_, _$q_) {
-      clusterService = _Cluster_;
-      deferred = _$q_.defer();
-      spyOn(clusterService, 'getStatus').andReturn(deferred.promise);
-      deferred.resolve({
-        Clusters: {
-          provisioning_state: 'INIT'
-        }
-      });
-      $window = _$window_;
-      $httpBackend = _$httpBackend_;
-      $httpBackend.whenGET(/api\/v1\/services\/AMBARI\/components\/AMBARI_SERVER.+/).respond(200, {
-        RootServiceComponents: {
-          component_version: 2.2,
-          properties: {
-            'user.inactivity.timeout.default': 20
-          }
-        }
-      });
-      $httpBackend.whenGET(/\/api\/v1\/views.+/).respond(200, {
-          "href": "http://c6401.ambari.apache.org:8080/api/v1/views?fields=versions/instances/ViewInstanceInfo&versions/ViewVersionInfo/system=false&versions/instances/ViewInstanceInfo/visible=true",
-          "items": [
-            {
-              "ViewInfo": {
-                "view_name": "SLIDER"
-              },
-              "href": "http://c6401.ambari.apache.org:8080/api/v1/views/SLIDER",
-              "versions": [
-                {
-                  "ViewVersionInfo": {
-                    "system": false,
-                    "version": "1.0.0",
-                    "view_name": "SLIDER"
-                  },
-                  "href": "http://c6401.ambari.apache.org:8080/api/v1/views/SLIDER/versions/1.0.0",
-                  "instances": [
-                    {
-                      "ViewInstanceInfo": {
-                        "context_path": "/views/SLIDER/1.0.0/VisibleInstance",
-                        "description": "VisibleInstance",
-                        "icon64_path": null,
-                        "icon_path": null,
-                        "instance_data": {},
-                        "instance_name": "VisibleInstance",
-                        "label": "VisibleInstance",
-                        "properties": {
-                          "ambari.server.password": "123",
-                          "ambari.server.url": "123",
-                          "ambari.server.username": "123",
-                          "slider.user": null,
-                          "view.kerberos.principal": null,
-                          "view.kerberos.principal.keytab": null
-                        },
-                        "static": false,
-                        "version": "1.0.0",
-                        "view_name": "SLIDER",
-                        "visible": true
-                      },
-                      "href": "http://c6401.ambari.apache.org:8080/api/v1/views/SLIDER/versions/1.0.0/instances/VisibleInstance"
-                    }
-                  ]
-                }
-              ]
-            }
-          ]
-        });
-      $httpBackend.whenGET(/\/persist\/user-pref-.*/).respond(200, {
-        data: {
-          data: {
-            addingNewRepository: true
-          }
-        }
-      });
-      scope = $rootScope.$new();
-      scope.$apply();
-      ctrl = $controller('MainCtrl', {
-        $scope: scope
-      });
-    });
-  });
-
-  afterEach(function() {
-    $httpBackend.verifyNoOutstandingExpectation();
-    $httpBackend.verifyNoOutstandingRequest();
-  });
-
-  describe('signout', function () {
-
-    beforeEach(function () {
-      $httpBackend.whenGET(/\/api\/v1\/logout\?_=\d+/).respond(200,{
-        message: "successfully logged out"
-      });
-      $httpBackend.whenGET(/\/api\/v1\/users\/admin\/authorizations.*/).respond(200, {
-        items: [
-          {
-            AuthorizationInfo: {
-              authorization_id: "AMBARI.RENAME_CLUSTER"
-            }
-          }
-        ]
-      });
-    });
-
-    it('should reset window.location and ambari localstorage', function () {
-      scope.signOut();
-
-      runs(function() {
-        chai.expect($window.location.pathname).to.equal('/');
-      });
-
-      var data = JSON.parse(localStorage.ambari);
-      chai.expect(data.app.authenticated).to.equal(undefined);
-      chai.expect(data.app.loginName).to.equal(undefined);
-      chai.expect(data.app.user).to.equal(undefined);
-      $httpBackend.flush();
-    });
-
-    it('should get visible view instances and show them in top nav menu', function() {
-      $httpBackend.flush();
-
-      chai.expect(scope.viewInstances.length).to.equal(1);
-      chai.expect(scope.viewInstances[0].instance_name).to.equal('VisibleInstance');
-    });
-  });
-
-  describe('roles loading', function () {
-
-    var mock = {
-        callback: angular.noop
-      },
-      cases = [
-        {
-          canPersistData: true,
-          items: [
-            {
-              AuthorizationInfo: {
-                authorization_id: 'CLUSTER.MANAGE_USER_PERSISTED_DATA'
-              }
-            }
-          ],
-          title: 'user can persist data'
-        },
-        {
-          canPersistData: false,
-          items: [],
-          title: 'user can\'t persist data'
-        }
-      ];
-
-    angular.forEach(cases, function (item) {
-
-      describe(item.title, function () {
-
-        beforeEach(function () {
-          $httpBackend.whenGET(/\/api\/v1\/users\/admin\/authorizations.*/).respond(200, {
-            items: item.items
-          });
-          spyOn(mock, 'callback');
-          scope.authDataLoad.promise.then(mock.callback);
-          $httpBackend.flush();
-        });
-
-        it('authDataLoad should be resolved with the correct argument', function () {
-          expect(mock.callback).toHaveBeenCalledWith(item.canPersistData);
-        });
-
-      });
-
-    });
-
-  });
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
new file mode 100644
index 0000000..8d04757
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/GroupsListCtrl_test.js
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+describe('#Cluster', function () {
+
+  describe('GroupsListCtrl', function() {
+
+    var scope, ctrl, $t, $httpBackend;
+
+    beforeEach(module('ambariAdminConsole', function () {}));
+
+    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+      scope = $rootScope.$new();
+      $t = _$translate_.instant;
+      $httpBackend = _$httpBackend_;
+      ctrl = $controller('GroupsListCtrl', {
+        $scope: scope
+      });
+    }));
+
+    describe('#clearFilters()', function () {
+
+      it('should clear filters and reset pagination', function () {
+        scope.currentPage = 2;
+        scope.filter.name = 'a';
+        scope.filter.type = {
+          label: $t('common.local'),
+          value: false
+        };
+        scope.clearFilters();
+        expect(scope.filter.name).toEqual('');
+        expect(scope.filter.type).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.currentPage).toEqual(1);
+      });
+
+    });
+
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          currentNameFilter: '',
+          currentTypeFilter: null,
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'type filter'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'both filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/groups/).respond(200);
+          scope.filter.name = item.currentNameFilter;
+          scope.filter.type = item.currentTypeFilter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
new file mode 100644
index 0000000..fcafa59
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/userManagement/UsersListCtrl_test.js
@@ -0,0 +1,344 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+describe('#Cluster', function () {
+
+  describe('UsersListCtrl', function() {
+
+    var scope, ctrl, $t, $httpBackend;
+
+    beforeEach(module('ambariAdminConsole', function () {}));
+
+    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
+      scope = $rootScope.$new();
+      $t = _$translate_.instant;
+      $httpBackend = _$httpBackend_;
+      ctrl = $controller('UsersListCtrl', {
+        $scope: scope
+      });
+    }));
+
+    describe('#clearFilters()', function () {
+
+      it('should clear filters and reset pagination', function () {
+        scope.currentPage = 2;
+        scope.filters.name = 'a';
+        scope.filters.status = {
+          label: $t('common.local'),
+          value: false
+        };
+        scope.filters.type = {
+          label: $t('common.local'),
+          value: 'LOCAL'
+        };
+        scope.clearFilters();
+        expect(scope.filters.name).toEqual('');
+        expect(scope.filters.status).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.filters.type).toEqual({
+          label: $t('common.all'),
+          value: '*'
+        });
+        expect(scope.currentPage).toEqual(1);
+      });
+
+    });
+
+    describe('#isNotEmptyFilter', function () {
+
+      var cases = [
+        {
+          currentNameFilter: '',
+          currentTypeFilter: null,
+          currentActiveFilter: null,
+          isNotEmptyFilter: false,
+          title: 'no filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: false,
+          title: 'empty filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name filter with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'type filter'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'activity filter'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'name and activity filters'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and admin filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and type filters with "0" as string'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'name and activity filters with "0" as string'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'name and admin filters with "0" as string'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'type and activity filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'type and admin filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'activity and admin filters'
+        },
+        {
+          currentNameFilter: '',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except name one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except type one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except activity one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters except admin one'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: '*'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string except type one'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: '*'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string except activity one'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: 'LOCAL'
+          },
+          currentActiveFilter: {
+            value: false
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string except admin one'
+        },
+        {
+          currentNameFilter: 'a',
+          currentTypeFilter: {
+            value: false
+          },
+          currentActiveFilter: {
+            value: 'LOCAL'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters'
+        },
+        {
+          currentNameFilter: '0',
+          currentTypeFilter: {
+            value: false
+          },
+          currentActiveFilter: {
+            value: 'LOCAL'
+          },
+          isNotEmptyFilter: true,
+          title: 'all filters with "0" as string'
+        }
+      ];
+
+      cases.forEach(function (item) {
+        it(item.title, function () {
+          $httpBackend.expectGET(/\/api\/v1\/users/).respond(200);
+          scope.filters.name = item.currentNameFilter;
+          scope.filters.status = item.currentActiveFilter;
+          scope.filters.type = item.currentTypeFilter;
+          scope.$digest();
+          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
+        });
+      });
+
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
deleted file mode 100644
index 9d6cd54..0000000
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/controllers/users/UsersListCtrl_test.js
+++ /dev/null
@@ -1,383 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-describe('#Cluster', function () {
-
-  describe('UsersListCtrl', function() {
-
-    var scope, ctrl, $t, $httpBackend;
-
-    beforeEach(module('ambariAdminConsole', function () {}));
-
-    beforeEach(inject(function($rootScope, $controller, _$translate_, _$httpBackend_) {
-      scope = $rootScope.$new();
-      $t = _$translate_.instant;
-      $httpBackend = _$httpBackend_;
-      ctrl = $controller('UsersListCtrl', {
-        $scope: scope
-      });
-    }));
-
-    describe('#clearFilters()', function () {
-
-      it('should clear filters and reset pagination', function () {
-        scope.currentPage = 2;
-        scope.currentNameFilter = 'a';
-        scope.currentActiveFilter = {
-          label: $t('common.local'),
-          value: false
-        };
-        scope.currentTypeFilter = {
-          label: $t('common.local'),
-          value: 'LOCAL'
-        };
-        scope.adminFilter = true;
-        scope.clearFilters();
-        expect(scope.currentNameFilter).toEqual('');
-        expect(scope.currentActiveFilter).toEqual({
-          label: $t('common.all'),
-          value: '*'
-        });
-        expect(scope.currentTypeFilter).toEqual({
-          label: $t('common.all'),
-          value: '*'
-        });
-        expect(scope.currentPage).toEqual(1);
-        expect(scope.adminFilter).toBe(false);
-      });
-
-    });
-
-    describe('#isNotEmptyFilter', function () {
-
-      var cases = [
-        {
-          currentNameFilter: '',
-          currentTypeFilter: null,
-          currentActiveFilter: null,
-          isNotEmptyFilter: false,
-          adminFilter: false,
-          title: 'no filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: false,
-          title: 'empty filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name filter'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name filter with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'type filter'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'activity filter'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'admin filter'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and type filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and activity filters'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'name and admin filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and type filters with "0" as string'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'name and activity filters with "0" as string'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'name and admin filters with "0" as string'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'type and activity filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'type and admin filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'activity and admin filters'
-        },
-        {
-          currentNameFilter: '',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters except name one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters except type one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters except activity one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'all filters except admin one'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: '*'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string except type one'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: '*'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string except activity one'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: 'LOCAL'
-          },
-          currentActiveFilter: {
-            value: false
-          },
-          adminFilter: false,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string except admin one'
-        },
-        {
-          currentNameFilter: 'a',
-          currentTypeFilter: {
-            value: false
-          },
-          currentActiveFilter: {
-            value: 'LOCAL'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters'
-        },
-        {
-          currentNameFilter: '0',
-          currentTypeFilter: {
-            value: false
-          },
-          currentActiveFilter: {
-            value: 'LOCAL'
-          },
-          adminFilter: true,
-          isNotEmptyFilter: true,
-          title: 'all filters with "0" as string'
-        }
-      ];
-
-      cases.forEach(function (item) {
-        it(item.title, function () {
-          $httpBackend.expectGET(/\/api\/v1\/users/).respond(200);
-          scope.currentNameFilter = item.currentNameFilter;
-          scope.currentActiveFilter = item.currentActiveFilter;
-          scope.currentTypeFilter = item.currentTypeFilter;
-          scope.adminFilter = item.adminFilter;
-          scope.$digest();
-          expect(scope.isNotEmptyFilter).toEqual(item.isNotEmptyFilter);
-        });
-      });
-
-    });
-
-  });
-
-});

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
----------------------------------------------------------------------
diff --git a/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js b/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
index 6b0b17f..7f67de4 100644
--- a/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
+++ b/ambari-admin/src/main/resources/ui/admin-web/test/unit/services/Utility_test.js
@@ -25,7 +25,13 @@ describe('Utility Service', function () {
 
   beforeEach(function () {
     module('ambariAdminConsole', function ($provide) {
-      $provide.value('$window', {});
+      $provide.value('$window', {
+        localStorage: {
+          getItem: function() {return '{}';},
+          setItem: function() {}
+        },
+        location: {}
+      });
     });
     inject(function (_Utility_, _$httpBackend_, $rootScope, $controller, _Cluster_, _$q_) {
       Utility = _Utility_;
@@ -39,7 +45,7 @@ describe('Utility Service', function () {
       });
       scope = $rootScope.$new();
       scope.$apply();
-      ctrl = $controller('MainCtrl', {
+      ctrl = $controller('AppCtrl', {
         $scope: scope
       });
       httpBackend.whenGET(/\/persist\/user-pref-.*/).respond(200, {});
@@ -54,6 +60,7 @@ describe('Utility Service', function () {
       httpBackend.whenGET(/\/api\/v1\/views.+/).respond(200, {
         items: []
       });
+      httpBackend.whenGET("views/clusters/clusterInformation.html").respond(200, {});
     });
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-agent/src/main/python/ambari_agent/AmbariAgent.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/AmbariAgent.py b/ambari-agent/src/main/python/ambari_agent/AmbariAgent.py
index 28b9528..aeb200c 100644
--- a/ambari-agent/src/main/python/ambari_agent/AmbariAgent.py
+++ b/ambari-agent/src/main/python/ambari_agent/AmbariAgent.py
@@ -49,9 +49,6 @@ def main():
 
   mergedArgs = [PYTHON, AGENT_SCRIPT] + args
 
-  # Become a parent for all subprocesses
-  os.setpgrp()
-
   try:
     while status == AGENT_AUTO_RESTART_EXIT_CODE:
       mainProcess = subprocess.Popen(mergedArgs)

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-agent/src/main/python/ambari_agent/Hardware.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/Hardware.py b/ambari-agent/src/main/python/ambari_agent/Hardware.py
index 696438e..56ce872 100644
--- a/ambari-agent/src/main/python/ambari_agent/Hardware.py
+++ b/ambari-agent/src/main/python/ambari_agent/Hardware.py
@@ -44,55 +44,72 @@ class Hardware:
   IGNORE_DEVICES = ["proc", "tmpfs", "cgroup", "mqueue", "shm"]
   LINUX_PATH_SEP = "/"
 
-  def __init__(self, config):
+  def __init__(self, config=None, cache_info=True):
+    """
+    Initialize hardware object with available metrics. Metrics cache could be
+     disabled by setting cache_info to False
+
+    :param config Ambari Agent Configuration
+    :param cache_info initialize hardware dictionary with available metrics
+
+    :type config AmbariConfig
+    :type cache_info bool
+    """
+    self.config = config
+    self._hardware = None
+
+    if cache_info:
+      self._cache_hardware_info()
+
+  def _cache_hardware_info(self):
+    """
+    Creating cache with hardware information
+    """
     logger.info("Initializing host system information.")
-    self.hardware = {
-      'mounts': Hardware.osdisks()
+    self._hardware = {
+      'mounts': self.osdisks()
     }
-    self.config = config
-    self.hardware.update(Facter(self.config).facterInfo())
-    logger.info("Host system information: %s", self.hardware)
+    self._hardware.update(Facter(self.config).facterInfo())
+    logger.info("Host system information: %s", self._hardware)
 
-  @classmethod
-  def _parse_df_line(cls, line):
+  def _parse_df(self, lines):
     """
-      Initialize data-structure from string in specific 'df' command output format
+      Generator, which parses df command output and yields parsed entities
 
       Expected string format:
        device fs_type disk_size used_size available_size capacity_used_percents mount_point
 
-    :type line str
+    :type lines list[str]
+    :rtype collections.Iterable
     """
+    titles = ["device", "type", "size", "used", "available", "percent", "mountpoint"]
 
-    line_split = line.split()
-    if len(line_split) != 7:
-      return None
+    for line in lines:
+      line_split = line.split()
+      if len(line_split) != 7:
+        continue
 
-    titles = ["device", "type", "size", "used", "available", "percent", "mountpoint"]
-    return dict(zip(titles, line_split))
+      yield dict(zip(titles, line_split))
 
-  @classmethod
-  def _get_mount_check_timeout(cls, config=None):
+  def _get_mount_check_timeout(self):
     """Return timeout for df call command"""
-    if config and config.has_option(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_TIMEOUT_KEY) \
-      and config.get(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_TIMEOUT_KEY) != "0":
+    if self.config and self.config.has_option(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_TIMEOUT_KEY) \
+      and self.config.get(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_TIMEOUT_KEY) != "0":
 
-      return config.get(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_TIMEOUT_KEY)
+      return self.config.get(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_TIMEOUT_KEY)
 
     return Hardware.CHECK_REMOTE_MOUNTS_TIMEOUT_DEFAULT
 
-  @classmethod
-  def _check_remote_mounts(cls, config=None):
+  def _check_remote_mounts(self):
     """Verify if remote mount allowed to be processed or not"""
-    if config and config.has_option(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_KEY) and \
-       config.get(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_KEY).lower() == "false":
+    if self.config and self.config.has_option(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_KEY) and \
+      self.config.get(AmbariConfig.AMBARI_PROPERTIES_CATEGORY, Hardware.CHECK_REMOTE_MOUNTS_KEY).lower() == "false":
 
       return False
 
     return True
 
-  @classmethod
-  def _is_mount_blacklisted(cls, blacklist, mount_point):
+  def _is_mount_blacklisted(self, blacklist, mount_point):
     """
     Verify if particular mount point is in the black list.
 
@@ -111,49 +128,44 @@ class Hardware:
     if not blacklist or not mount_point:
       return False
 
-    mount_point_elements = mount_point.split(cls.LINUX_PATH_SEP)
+    # in this way we excluding possibility
+    mount_point_elements = mount_point.split(self.LINUX_PATH_SEP)
 
     for el in blacklist:
-      el_list = el.split(cls.LINUX_PATH_SEP)
+      el_list = el.split(self.LINUX_PATH_SEP)
       # making patch elements comparision
       if el_list == mount_point_elements[:len(el_list)]:
         return True
 
     return False
 
-
-  @classmethod
   @OsFamilyFuncImpl(OsFamilyImpl.DEFAULT)
-  def osdisks(cls, config=None):
+  def osdisks(self):
     """ Run df to find out the disks on the host. Only works on linux
     platforms. Note that this parser ignores any filesystems with spaces
     and any mounts with spaces. """
-    timeout = cls._get_mount_check_timeout(config)
+    timeout = self._get_mount_check_timeout()
     command = ["timeout", timeout, "df", "-kPT"]
     blacklisted_mount_points = []
 
-    if config:
-      ignore_mount_value = config.get("agent", "ignore_mount_points", default="")
-      blacklisted_mount_points = [item.strip() for item in ignore_mount_value.split(",")]
+    if self.config:
+      ignore_mount_value = self.config.get("agent", "ignore_mount_points", default="")
+      blacklisted_mount_points = [item.strip() for item in ignore_mount_value.split(",") if len(item.strip()) != 0]
 
-    if not cls._check_remote_mounts(config):
+    if not self._check_remote_mounts():
       command.append("-l")
 
     try:
-      code, out, err = shell.call(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE, timeout = int(timeout), quiet = True)
+      code, out, err = shell.call(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=int(timeout), quiet=True)
       dfdata = out
     except Exception as ex:
       logger.warn("Checking disk usage failed: " + str(ex))
       dfdata = ''
 
-    mounts = [cls._parse_df_line(line) for line in dfdata.splitlines() if line]
     result_mounts = []
     ignored_mounts = []
 
-    for mount in mounts:
-      if not mount:
-        continue
-
+    for mount in self._parse_df(dfdata.splitlines()):
       """
       We need to filter mounts by several parameters:
        - mounted device is not in the ignored list
@@ -161,11 +173,11 @@ class Hardware:
        - it is not file-mount (docker environment)
        - mount path or a part of mount path is not in the blacklist
       """
-      if mount["device"] not in cls.IGNORE_DEVICES and\
-         mount["mountpoint"].split("/")[0] not in cls.IGNORE_ROOT_MOUNTS and\
-         cls._chk_writable_mount(mount['mountpoint']) and\
+      if mount["device"] not in self.IGNORE_DEVICES and\
+         mount["mountpoint"].split("/")[0] not in self.IGNORE_ROOT_MOUNTS and\
+         self._chk_writable_mount(mount['mountpoint']) and\
          not path_isfile(mount["mountpoint"]) and\
-         not cls._is_mount_blacklisted(blacklisted_mount_points, mount["mountpoint"]):
+         not self._is_mount_blacklisted(blacklisted_mount_points, mount["mountpoint"]):
 
         result_mounts.append(mount)
       else:
@@ -177,8 +189,7 @@ class Hardware:
 
     return result_mounts
 
-  @classmethod
-  def _chk_writable_mount(cls, mount_point):
+  def _chk_writable_mount(self, mount_point):
     if os.geteuid() == 0:
       return os.access(mount_point, os.W_OK)
     else:
@@ -196,9 +207,8 @@ class Hardware:
         logger.exception("Exception happened while checking mount {0}".format(mount_point))
         return False
     
-  @classmethod
   @OsFamilyFuncImpl(OSConst.WINSRV_FAMILY)
-  def osdisks(cls, config=None):
+  def osdisks(self):
     mounts = []
     runner = shellRunner()
     command_result = runner.runPowershell(script_block=Hardware.WINDOWS_GET_DRIVES_CMD)
@@ -216,16 +226,28 @@ class Hardware:
 
     return mounts
 
-  def get(self):
-    return self.hardware
+  def get(self, invalidate_cache=False):
+    """
+    Getting cached hardware information
+
+    :param invalidate_cache resets hardware metrics cache
+    :type invalidate_cache bool
+    """
+    if invalidate_cache:
+      self._hardware = None
+
+    if not self._hardware:
+      self._cache_hardware_info()
+
+    return self._hardware
 
 
 def main():
   from resource_management.core.logger import Logger
   Logger.initialize_logger()
 
-  config = None
-  print Hardware(config).get()
+  print Hardware().get()
+
 
 if __name__ == '__main__':
   main()

http://git-wip-us.apache.org/repos/asf/ambari/blob/e83bf1bd/ambari-agent/src/main/python/ambari_agent/Heartbeat.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/Heartbeat.py b/ambari-agent/src/main/python/ambari_agent/Heartbeat.py
index 1e05aae..d7c0325 100644
--- a/ambari-agent/src/main/python/ambari_agent/Heartbeat.py
+++ b/ambari-agent/src/main/python/ambari_agent/Heartbeat.py
@@ -75,14 +75,11 @@ class Heartbeat:
     if int(id) == 0:
       componentsMapped = False
 
-
-
     logger.debug("Building Heartbeat: {responseId = %s, timestamp = %s, "
                 "commandsInProgress = %s, componentsMapped = %s,"
                 "recoveryTimestamp = %s}",
         str(id), str(timestamp), repr(commandsInProgress), repr(componentsMapped), str(recovery_timestamp))
 
-
     logger.debug("Heartbeat: %s", pformat(heartbeat))
 
     hostInfo = HostInfo(self.config)
@@ -93,10 +90,9 @@ class Heartbeat:
       # this must be the last step before returning heartbeat
       hostInfo.register(nodeInfo, componentsMapped, commandsInProgress)
       heartbeat['agentEnv'] = nodeInfo
-      mounts = Hardware.osdisks(self.config)
+      mounts = Hardware(config=self.config, cache_info=False).osdisks()
       heartbeat['mounts'] = mounts
 
-
       logger.debug("agentEnv: %s", str(nodeInfo))
       logger.debug("mounts: %s", str(mounts))
 
@@ -105,6 +101,7 @@ class Heartbeat:
     
     return heartbeat
 
+
 def main(argv=None):
   from ambari_agent.ActionQueue import ActionQueue
   from ambari_agent.AmbariConfig import AmbariConfig
@@ -122,5 +119,6 @@ def main(argv=None):
   heartbeat = Heartbeat(actionQueue)
   print json.dumps(heartbeat.build('3',3))
 
+
 if __name__ == '__main__':
   main()