You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2014/09/27 02:28:36 UTC

[1/3] git commit: AMBARI-7529. On upgrade to 1.7.0, automatically create Jobs view instance.

Repository: ambari
Updated Branches:
  refs/heads/trunk dcedac206 -> be13513cf


AMBARI-7529. On upgrade to 1.7.0, automatically create Jobs view instance.


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

Branch: refs/heads/trunk
Commit: 1ea0f474ee9316dbb18beda3cec6935d3ffc14f3
Parents: dcedac2
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Fri Sep 26 16:57:41 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Fri Sep 26 16:57:41 2014 -0700

----------------------------------------------------------------------
 .../server/upgrade/UpgradeCatalog170.java       | 139 +++++++++++++------
 .../apache/ambari/server/view/ViewRegistry.java |  26 +++-
 .../server/upgrade/UpgradeCatalog170Test.java   |  63 +++++++--
 .../ambari/server/upgrade/UpgradeTest.java      |  11 +-
 contrib/views/jobs/src/main/resources/view.xml  |   4 +-
 5 files changed, 181 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
index 6693e20..d86bf35 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
@@ -46,6 +46,7 @@ import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
+import org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity;
 import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
@@ -70,6 +71,7 @@ import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.utils.StageUtils;
+import org.apache.ambari.server.view.ViewRegistry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -115,9 +117,16 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
   private static final String ALERT_TABLE_GROUPING = "alert_grouping";
   private static final String ALERT_TABLE_NOTICE = "alert_notice";
   public static final String JOBS_VIEW_NAME = "JOBS";
+  public static final String VIEW_NAME_REG_EXP = JOBS_VIEW_NAME + "\\{.*\\}";
   public static final String JOBS_VIEW_INSTANCE_NAME = "JOBS_1";
   public static final String SHOW_JOBS_FOR_NON_ADMIN_KEY = "showJobsForNonAdmin";
   public static final String JOBS_VIEW_INSTANCE_LABEL = "Jobs";
+  public static final String CLUSTER_STATE_STACK_HDP_2_1 = "{\"stackName\":\"HDP\",\"stackVersion\":\"2.1\"}";
+  public static final String YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY = "yarn.timeline-service.webapp.address";
+  public static final String YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY = "yarn.resourcemanager.webapp.address";
+  public static final String YARN_SITE = "yarn-site";
+  public static final String YARN_ATS_URL_PROPERTY = "yarn.ats.url";
+  public static final String YARN_RESOURCEMANAGER_URL_PROPERTY = "yarn.resourcemanager.url";
 
   //SourceVersion is only for book-keeping purpos
   @Override
@@ -1295,56 +1304,96 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
     final KeyValueDAO keyValueDAO = injector.getInstance(KeyValueDAO.class);
     final PermissionDAO permissionDAO = injector.getInstance(PermissionDAO.class);
     final PrivilegeDAO privilegeDAO = injector.getInstance(PrivilegeDAO.class);
-
-    ViewEntity jobsView = viewDAO.findByCommonName(JOBS_VIEW_NAME);
-    if (jobsView != null) {
-      ViewInstanceEntity jobsInstance = jobsView.getInstanceDefinition(JOBS_VIEW_INSTANCE_NAME);
-      if (jobsInstance == null) {
-        jobsInstance = new ViewInstanceEntity(jobsView, JOBS_VIEW_INSTANCE_NAME, JOBS_VIEW_INSTANCE_LABEL);
-        ResourceEntity resourceEntity = new ResourceEntity();
-        resourceEntity.setResourceType(resourceTypeDAO.findByName(
-            ViewEntity.getViewName(
-                jobsView.getCommonName(),
-                jobsView.getVersion())));
-        jobsInstance.setResource(resourceEntity);
-        jobsView.addInstanceDefinition(jobsInstance);
-        resourceDAO.create(resourceEntity);
-        viewInstanceDAO.create(jobsInstance);
-        viewDAO.merge(jobsView);
-      }
-      // get showJobsForNonAdmin value and remove it
-      boolean showJobsForNonAdmin = false;
-      KeyValueEntity showJobsKeyValueEntity = keyValueDAO.findByKey(SHOW_JOBS_FOR_NON_ADMIN_KEY);
-      if (showJobsKeyValueEntity != null) {
-        String value = showJobsKeyValueEntity.getValue();
-        showJobsForNonAdmin = Boolean.parseBoolean(value);
-        keyValueDAO.remove(showJobsKeyValueEntity);
-      }
-      if (showJobsForNonAdmin) {
-        ResourceEntity jobsResource = jobsInstance.getResource();
-        PermissionEntity viewUsePermission = permissionDAO.findViewUsePermission();
-        for (UserEntity userEntity : userDAO.findAll()) {
-          // check if user has VIEW.USE privilege for JOBS view
-          List<PrivilegeEntity> privilegeEntities = privilegeDAO.findAllByPrincipal(
-              Collections.singletonList(userEntity.getPrincipal()));
-          boolean hasJobsUsePrivilege = false;
-          for (PrivilegeEntity privilegeEntity : privilegeEntities) {
-            if (privilegeEntity.getResource().getId() == jobsInstance.getResource().getId() &&
-                privilegeEntity.getPermission().getId() == viewUsePermission.getId()) {
-              hasJobsUsePrivilege = true;
-              break;
+    final ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+    final ViewRegistry viewRegistry = injector.getInstance(ViewRegistry.class);
+
+    List<ClusterEntity> clusters = clusterDAO.findAll();
+    if (!clusters.isEmpty()) {
+      ClusterEntity currentCluster = clusters.get(0);
+      String currentStackVersion = currentCluster.getClusterStateEntity().getCurrentStackVersion();
+      if (CLUSTER_STATE_STACK_HDP_2_1.equals(currentStackVersion)) {
+        ViewRegistry.initInstance(viewRegistry);
+        viewRegistry.readViewArchives(VIEW_NAME_REG_EXP);
+        ViewEntity jobsView = viewDAO.findByCommonName(JOBS_VIEW_NAME);
+
+        if (jobsView != null) {
+          ViewInstanceEntity jobsInstance = jobsView.getInstanceDefinition(JOBS_VIEW_INSTANCE_NAME);
+          if (jobsInstance == null) {
+            jobsInstance = new ViewInstanceEntity(jobsView, JOBS_VIEW_INSTANCE_NAME, JOBS_VIEW_INSTANCE_LABEL);
+            ResourceEntity resourceEntity = new ResourceEntity();
+            resourceEntity.setResourceType(resourceTypeDAO.findByName(
+                ViewEntity.getViewName(
+                    jobsView.getCommonName(),
+                    jobsView.getVersion())));
+            String atsHost;
+            String rmHost;
+            try {
+              ClusterConfigEntity currentYarnConfig = null;
+              for (ClusterConfigMappingEntity configMappingEntity : currentCluster.getConfigMappingEntities()) {
+                if (YARN_SITE.equals(configMappingEntity.getType()) && configMappingEntity.isSelected() > 0) {
+                  currentYarnConfig = clusterDAO.findConfig(currentCluster.getClusterId(),
+                      configMappingEntity.getType(), configMappingEntity.getTag());
+                  break;
+                }
+              }
+              Type type = new TypeToken<Map<String, String>>() {}.getType();
+              Map<String, String> yarnSiteProps = StageUtils.getGson().fromJson(currentYarnConfig.getData(), type);
+              atsHost = yarnSiteProps.get(YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY);
+              rmHost = yarnSiteProps.get(YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY);
+            } catch (Exception ex) {
+              // Required properties failed to be set, therefore jobs instance should not be created
+              return;
             }
+            jobsInstance.setResource(resourceEntity);
+            jobsInstance.putProperty(YARN_ATS_URL_PROPERTY, "http://" + atsHost);
+            jobsInstance.putProperty(YARN_RESOURCEMANAGER_URL_PROPERTY, "http://" + rmHost);
+            jobsView.addInstanceDefinition(jobsInstance);
+            resourceDAO.create(resourceEntity);
+            viewInstanceDAO.create(jobsInstance);
+            viewDAO.merge(jobsView);
           }
-          // if not - add VIEW.use privilege
-          if (!hasJobsUsePrivilege) {
-            PrivilegeEntity privilegeEntity = new PrivilegeEntity();
-            privilegeEntity.setResource(jobsResource);
-            privilegeEntity.setPermission(viewUsePermission);
-            privilegeEntity.setPrincipal(userEntity.getPrincipal());
-            privilegeDAO.create(privilegeEntity);
+          // get showJobsForNonAdmin value and remove it
+          boolean showJobsForNonAdmin = false;
+          KeyValueEntity showJobsKeyValueEntity = keyValueDAO.findByKey(SHOW_JOBS_FOR_NON_ADMIN_KEY);
+          if (showJobsKeyValueEntity != null) {
+            String value = showJobsKeyValueEntity.getValue();
+            showJobsForNonAdmin = Boolean.parseBoolean(value);
+            keyValueDAO.remove(showJobsKeyValueEntity);
+          }
+          if (showJobsForNonAdmin) {
+            ResourceEntity jobsResource = jobsInstance.getResource();
+            long jobsResourceId = jobsResource.getId();
+            PermissionEntity viewUsePermission = permissionDAO.findViewUsePermission();
+            PermissionEntity adminPermission = permissionDAO.findAmbariAdminPermission();
+            int viewUsePermissionId = viewUsePermission.getId();
+            int adminPermissionId = adminPermission.getId();
+            for (UserEntity userEntity : userDAO.findAll()) {
+              // check if user has VIEW.USE privilege for JOBS view
+              List<PrivilegeEntity> privilegeEntities = privilegeDAO.findAllByPrincipal(
+                  Collections.singletonList(userEntity.getPrincipal()));
+              boolean hasJobsUsePrivilege = false;
+              for (PrivilegeEntity privilegeEntity : privilegeEntities) {
+                int privilegePermissionId = privilegeEntity.getPermission().getId();
+                Long privilegeResourceId = privilegeEntity.getResource().getId();
+                if ((privilegePermissionId == viewUsePermissionId && privilegeResourceId == jobsResourceId)
+                    || privilegePermissionId == adminPermissionId) {
+                  hasJobsUsePrivilege = true;
+                  break;
+                }
+              }
+              // if not - add VIEW.use privilege
+              if (!hasJobsUsePrivilege) {
+                PrivilegeEntity privilegeEntity = new PrivilegeEntity();
+                privilegeEntity.setResource(jobsResource);
+                privilegeEntity.setPermission(viewUsePermission);
+                privilegeEntity.setPrincipal(userEntity.getPrincipal());
+                privilegeDAO.create(privilegeEntity);
+              }
+            }
           }
         }
       }
     }
+
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index 58c4334..5f775a6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -102,6 +102,7 @@ public class ViewRegistry {
    */
   private static final String EXTRACTED_ARCHIVES_DIR = "work";
   private static final String EXTRACT_COMMAND = "extract";
+  private static final String ALL_VIEWS_REG_EXP = ".*";
 
   /**
    * Thread pool
@@ -424,10 +425,19 @@ public class ViewRegistry {
   }
 
   /**
-   * Read the view archives.
+   * Read all view archives.
    */
   public void readViewArchives() {
-    readViewArchives(false, true);
+    readViewArchives(false, true, ALL_VIEWS_REG_EXP, true);
+  }
+
+  /**
+   * Read only view archives with names corresponding to given regular expression.
+   *
+   * @param viewNameRegExp view name regular expression
+   */
+  public void readViewArchives(String viewNameRegExp) {
+    readViewArchives(false, false, viewNameRegExp, false);
   }
 
   /**
@@ -1147,9 +1157,9 @@ public class ViewRegistry {
     }
   }
 
-
   // read the view archives.
-  private void readViewArchives(boolean systemOnly, boolean useExecutor) {
+  private void readViewArchives(boolean systemOnly, boolean useExecutor,
+                                String viewNameRegExp, boolean removeUndeployed) {
     try {
       File viewDir = configuration.getViewsDir();
 
@@ -1173,6 +1183,10 @@ public class ViewRegistry {
               String version    = viewConfig.getVersion();
               String viewName   = ViewEntity.getViewName(commonName, version);
 
+              if (!viewName.matches(viewNameRegExp)) {
+                continue;
+              }
+
               final String extractedArchiveDirPath = extractedArchivesPath + File.separator + viewName;
               final File extractedArchiveDirFile = archiveUtility.getFile(extractedArchiveDirPath);
 
@@ -1210,7 +1224,9 @@ public class ViewRegistry {
             }
           }
 
-          removeUndeployedViews();
+          if (removeUndeployed) {
+            removeUndeployedViews();
+          }
         }
       } else {
         LOG.error("Could not create extracted view archive directory " + extractedArchivesPath + ".");

http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
index 2edc5b5..0c92f44 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
@@ -18,6 +18,13 @@
 
 package org.apache.ambari.server.upgrade;
 
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.CLUSTER_STATE_STACK_HDP_2_1;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.JOBS_VIEW_NAME;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.SHOW_JOBS_FOR_NON_ADMIN_KEY;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.YARN_SITE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY;
+
 import com.google.inject.Binder;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -49,8 +56,10 @@ import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.dao.ViewDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
+import org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
+import org.apache.ambari.server.orm.entities.ClusterStateEntity;
 import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntityPK;
@@ -59,6 +68,7 @@ import org.apache.ambari.server.orm.entities.HostComponentStateEntityPK;
 import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
 import org.apache.ambari.server.orm.entities.KeyValueEntity;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
@@ -74,7 +84,9 @@ import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.HostComponentAdminState;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.view.ViewRegistry;
 import org.easymock.Capture;
+import org.easymock.IAnswer;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -116,6 +128,7 @@ import static org.easymock.EasyMock.createStrictMock;
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.getCurrentArguments;
 import static org.easymock.EasyMock.isA;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.reset;
@@ -422,6 +435,9 @@ public class UpgradeCatalog170Test {
     Clusters clusters = createStrictMock(Clusters.class);
     Config config = createStrictMock(Config.class);
     Config pigConfig = createStrictMock(Config.class);
+    ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
+    PermissionEntity adminPermission = createNiceMock(PermissionEntity.class);
+    PermissionEntity viewUsePermission = createNiceMock(PermissionEntity.class);
 
     ClusterConfigEntity clusterConfigEntity = createNiceMock(ClusterConfigEntity.class);
     ConfigGroupConfigMappingDAO configGroupConfigMappingDAO = createNiceMock(ConfigGroupConfigMappingDAO.class);
@@ -448,6 +464,8 @@ public class UpgradeCatalog170Test {
     TypedQuery<HostRoleCommandEntity> q = createNiceMock(TypedQuery.class);
     List<HostRoleCommandEntity> r = new ArrayList<HostRoleCommandEntity>();
     ResultSet userRolesResultSet = createNiceMock(ResultSet.class);
+    ClusterEntity clusterEntity = createNiceMock(ClusterEntity.class);
+    ClusterConfigEntity configEntity = createNiceMock(ClusterConfigEntity.class);
 
     Method m = AbstractUpgradeCatalog.class.getDeclaredMethod
         ("updateConfigurationProperties", String.class, Map.class, boolean.class, boolean.class);
@@ -543,13 +561,20 @@ public class UpgradeCatalog170Test {
     expect(injector.getInstance(PermissionDAO.class)).andReturn(permissionDAO).anyTimes();
     expect(injector.getInstance(PrivilegeDAO.class)).andReturn(privilegeDAO).anyTimes();
     expect(injector.getInstance(KeyValueDAO.class)).andReturn(keyValueDAO).anyTimes();
+    expect(injector.getInstance(ViewRegistry.class)).andReturn(viewRegistry).anyTimes();
 
+    String yarnConfig = String.format("{'%s':'%s', '%s':'%s'}",
+        YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY, "timeline:8081",
+        YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY, "resource_man:8081");
     expect(configGroupConfigMappingDAO.findAll()).andReturn(configGroupConfigMappingEntities).once();
-    expect(userDAO.findAll()).andReturn(Collections.<UserEntity> emptyList()).times(2);
-    expect(clusterDAO.findAll()).andReturn(Collections.<ClusterEntity> emptyList()).anyTimes();
+    expect(userDAO.findAll()).andReturn(Collections.<UserEntity>emptyList()).times(2);
+    expect(clusterDAO.findAll()).andReturn(Collections.singletonList(clusterEntity)).anyTimes();
+    expect(configEntity.getData()).andReturn(yarnConfig);
+    expect(clusterDAO.findConfig(1L, YARN_SITE, "version1")).andReturn(configEntity).anyTimes();
     expect(viewDAO.findAll()).andReturn(Collections.<ViewEntity> emptyList()).anyTimes();
     expect(viewInstanceDAO.findAll()).andReturn(Collections.<ViewInstanceEntity> emptyList()).anyTimes();
-    expect(permissionDAO.findAmbariAdminPermission()).andReturn(null);
+    expect(permissionDAO.findAmbariAdminPermission()).andReturn(adminPermission).anyTimes();
+    expect(permissionDAO.findViewUsePermission()).andReturn(viewUsePermission).anyTimes();
     expect(permissionDAO.findClusterOperatePermission()).andReturn(null);
     expect(permissionDAO.findClusterReadPermission()).andReturn(null);
 
@@ -559,18 +584,36 @@ public class UpgradeCatalog170Test {
     ViewEntity jobsView = createNiceMock(ViewEntity.class);
     KeyValueEntity showJobsKeyValue = createNiceMock(KeyValueEntity.class);
     UserEntity user = createNiceMock(UserEntity.class);
-
+    ClusterConfigMappingEntity configMappingEntity = createNiceMock(ClusterConfigMappingEntity.class);
+    ClusterStateEntity clusterStateEntity = createNiceMock(ClusterStateEntity.class);
+
+    expect(clusterEntity.getClusterId()).andReturn(1L).anyTimes();
+    expect(clusterEntity.getConfigMappingEntities()).andReturn(Collections.singleton(configMappingEntity));
+    expect(clusterEntity.getClusterStateEntity()).andReturn(clusterStateEntity).anyTimes();
+    expect(clusterStateEntity.getCurrentStackVersion()).andReturn(CLUSTER_STATE_STACK_HDP_2_1);
+    expect(configMappingEntity.getType()).andReturn(YARN_SITE).anyTimes();
+    expect(configMappingEntity.isSelected()).andReturn(1).anyTimes();
+    expect(configMappingEntity.getTag()).andReturn("version1");
     expect(userDAO.findAll()).andReturn(Collections.singletonList(user));
-    expect(jobsView.getCommonName()).andReturn(UpgradeCatalog170.JOBS_VIEW_NAME);
+    expect(jobsView.getCommonName()).andReturn(JOBS_VIEW_NAME);
     expect(jobsView.getVersion()).andReturn("1.0.0");
-    expect(viewDAO.findByCommonName(UpgradeCatalog170.JOBS_VIEW_NAME)).andReturn(jobsView).once();
+    expect(viewDAO.findByCommonName(JOBS_VIEW_NAME)).andReturn(jobsView).once();
     expect(showJobsKeyValue.getValue()).andReturn("true");
-    expect(keyValueDAO.findByKey(UpgradeCatalog170.SHOW_JOBS_FOR_NON_ADMIN_KEY)).andReturn(showJobsKeyValue);
+    expect(keyValueDAO.findByKey(SHOW_JOBS_FOR_NON_ADMIN_KEY)).andReturn(showJobsKeyValue);
     expect(privilegeDAO.findAllByPrincipal(anyObject(List.class))).andReturn(Collections.<PrivilegeEntity>emptyList());
     expect(viewDAO.merge(jobsView)).andReturn(jobsView);
 
     resourceDAO.create(anyObject(ResourceEntity.class));
+    expect(adminPermission.getId()).andReturn(3);
+    expect(viewUsePermission.getId()).andReturn(4);
     viewInstanceDAO.create(anyObject(ViewInstanceEntity.class));
+    expectLastCall().andAnswer(new IAnswer<Object>() {
+      @Override
+      public Object answer() throws Throwable {
+        ((ViewInstanceEntity) getCurrentArguments()[0]).getResource().setId(1L);
+        return null;
+      }
+    });
     keyValueDAO.remove(showJobsKeyValue);
     privilegeDAO.create(anyObject(PrivilegeEntity.class));
 
@@ -579,7 +622,8 @@ public class UpgradeCatalog170Test {
     replay(dbAccessor, configuration, injector, cluster, clusters, amc, config, configHelper, pigConfig);
     replay(userDAO, clusterDAO, viewDAO, viewInstanceDAO, permissionDAO, configGroupConfigMappingDAO);
     replay(resourceTypeDAO, resourceDAO, keyValueDAO, privilegeDAO, clusterConfigEntity);
-    replay(jobsView, showJobsKeyValue, user);
+    replay(jobsView, showJobsKeyValue, user, viewRegistry, viewUsePermission, adminPermission);
+    replay(clusterEntity, configEntity, configMappingEntity, clusterStateEntity);
 
     Class<?> c = AbstractUpgradeCatalog.class;
     Field f = c.getDeclaredField("configuration");
@@ -595,7 +639,8 @@ public class UpgradeCatalog170Test {
     upgradeCatalog.executeDMLUpdates();
 
     verify(upgradeCatalog, dbAccessor, configuration, injector, cluster, clusters, amc, config, configHelper,
-        jobsView, showJobsKeyValue, privilegeDAO, viewDAO, viewInstanceDAO, resourceDAO, keyValueDAO, userRolesResultSet);
+        jobsView, showJobsKeyValue, privilegeDAO, viewDAO, viewInstanceDAO, resourceDAO, keyValueDAO,
+        viewRegistry, userRolesResultSet, clusterEntity, configEntity, configMappingEntity, clusterStateEntity);
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
index c89a0b4..b70d252 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
@@ -28,6 +28,8 @@ import org.apache.ambari.server.controller.ControllerModule;
 import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.dao.*;
 import org.apache.ambari.server.utils.VersionUtils;
+import org.apache.ambari.server.view.ViewRegistry;
+import org.easymock.EasyMock;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -148,7 +150,14 @@ public class UpgradeTest {
   }
 
   private void performUpgrade(String targetVersion) throws Exception {
-    Injector injector = Guice.createInjector(new SchemaUpgradeHelper.UpgradeHelperModule(properties));
+    Injector injector = Guice.createInjector(new SchemaUpgradeHelper.UpgradeHelperModule(properties) {
+      @Override
+      protected void configure() {
+        super.configure();
+        ViewRegistry viewRegistryMock = EasyMock.createNiceMock(ViewRegistry.class);
+        bind(ViewRegistry.class).toInstance(viewRegistryMock);
+      }
+    });
     SchemaUpgradeHelper schemaUpgradeHelper = injector.getInstance(SchemaUpgradeHelper.class);
 
     LOG.info("Upgrading schema to target version = " + targetVersion);

http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/contrib/views/jobs/src/main/resources/view.xml
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/view.xml b/contrib/views/jobs/src/main/resources/view.xml
index 30adca2..6dd5ee6 100644
--- a/contrib/views/jobs/src/main/resources/view.xml
+++ b/contrib/views/jobs/src/main/resources/view.xml
@@ -21,11 +21,11 @@ limitations under the License. Kerberos, LDAP, Custom. Binary/Htt
   <parameter>
       <name>yarn.ats.url</name>
       <description>The URL to the YARN Application Timeline Server, used to provide Jobs information, typically, this is the yarn.timeline-service.webapp.address property in the yarn-site.xml configuration. For example: http://yarn.ats.address:8188</description>
-      <required>false</required>
+      <required>true</required>
   </parameter>
   <parameter>
       <name>yarn.resourcemanager.url</name>
       <description>The URL to the YARN ResourceManager, used to provide YARN Application data. For example: http://yarn.resourcemanager.address:8088</description>
-      <required>false</required>
+      <required>true</required>
   </parameter>
 </view>


[3/3] git commit: AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN. Missing import.

Posted by sw...@apache.org.
AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN. Missing import.


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

Branch: refs/heads/trunk
Commit: be13513cf3db7cfc7a16d64766db95b5dd1e19bf
Parents: f92ad8f
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Fri Sep 26 17:28:04 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Fri Sep 26 17:28:04 2014 -0700

----------------------------------------------------------------------
 .../server/security/authorization/AmbariAuthorizationFilter.java    | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/be13513c/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
index f1c2a26..b184a59 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.security.authorization;
 
 import java.io.IOException;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.servlet.Filter;


[2/3] git commit: AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN.

Posted by sw...@apache.org.
AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN.


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

Branch: refs/heads/trunk
Commit: f92ad8f520b230feaf6c0bc7d8c7248448566e0b
Parents: 1ea0f47
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Fri Sep 26 17:15:55 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Fri Sep 26 17:15:55 2014 -0700

----------------------------------------------------------------------
 .../server/orm/entities/ViewInstanceEntity.java |  34 +--
 .../AmbariAuthorizationFilter.java              |  81 +++++-
 .../server/security/authorization/Users.java    |   3 +-
 .../orm/entities/ViewInstanceEntityTest.java    |  19 +-
 .../AmbariAuthorizationFilterTest.java          | 266 ++++++++++++++++++-
 .../security/authorization/TestUsers.java       |   1 +
 6 files changed, 335 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
index f84be60..8f8712c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
@@ -23,9 +23,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -47,6 +44,7 @@ import javax.persistence.UniqueConstraint;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.security.SecurityHelper;
 import org.apache.ambari.server.security.SecurityHelperImpl;
+import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.view.ResourceProvider;
 import org.apache.ambari.view.ViewDefinition;
@@ -70,15 +68,6 @@ import org.apache.ambari.view.ViewInstanceDefinition;
 )
 @Entity
 public class ViewInstanceEntity implements ViewInstanceDefinition {
-  /**
-   * The prefix for every view instance context path.
-   */
-  public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
-
-  /**
-   * The pattern for matching view instance context path.
-   */
-  public static final String VIEWS_CONTEXT_PATH_PATTERN = "" + VIEWS_CONTEXT_PATH_PREFIX + "([^/]+)/([^/]+)/([^/]+)(.*)";
 
   @Id
   @Column(name = "view_instance_id", nullable = false)
@@ -680,26 +669,7 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
    * @return the context path
    */
   public static String getContextPath(String viewName, String version, String viewInstanceName) {
-    return VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + version + "/" + viewInstanceName;
-  }
-
-  /**
-   * Parses context path into view name, version and instance name
-   *
-   * @param contextPath the context path
-   * @return null if context path doesn't match correct pattern
-   */
-  public static ViewInstanceVersionDTO parseContextPath(String contextPath) {
-    final Pattern pattern = Pattern.compile(VIEWS_CONTEXT_PATH_PATTERN);
-    Matcher matcher = pattern.matcher(contextPath);
-    if (!matcher.matches()) {
-      return null;
-    } else {
-      final String viewName = matcher.group(1);
-      final String version = matcher.group(2);
-      final String instanceName = matcher.group(3);
-      return new ViewInstanceVersionDTO(viewName, version, instanceName);
-    }
+    return AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + version + "/" + viewInstanceName;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
index 658fc80..f1c2a26 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
@@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
 import org.apache.ambari.server.security.authorization.internal.InternalAuthenticationToken;
 import org.apache.ambari.server.view.ViewRegistry;
@@ -50,6 +49,19 @@ public class AmbariAuthorizationFilter implements Filter {
 
   private static final Pattern STACK_ADVISOR_REGEX = Pattern.compile("/api/v[0-9]+/stacks/[^/]+/versions/[^/]+/validations.*");
 
+  public static final String API_VERSION_PREFIX        = "/api/v[0-9]+";
+  public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
+
+  private static final String VIEWS_CONTEXT_PATH_PATTERN       = VIEWS_CONTEXT_PATH_PREFIX + "([^/]+)/([^/]+)/([^/]+)(.*)";
+  private static final String VIEWS_CONTEXT_ALL_PATTERN        = VIEWS_CONTEXT_PATH_PREFIX + ".*";
+  private static final String API_USERS_USERNAME_PATTERN       = API_VERSION_PREFIX + "/users/([^/?]+)(.*)";
+  private static final String API_USERS_ALL_PATTERN            = API_VERSION_PREFIX + "/users.*";
+  private static final String API_GROUPS_ALL_PATTERN           = API_VERSION_PREFIX + "/groups.*";
+  private static final String API_CLUSTERS_ALL_PATTERN         = API_VERSION_PREFIX + "/clusters.*";
+  private static final String API_VIEWS_ALL_PATTERN            = API_VERSION_PREFIX + "/views.*";
+  private static final String API_PERSIST_ALL_PATTERN          = API_VERSION_PREFIX + "/persist.*";
+  private static final String API_LDAP_SYNC_EVENTS_ALL_PATTERN = API_VERSION_PREFIX + "/ldap_sync_events.*";
+
   /**
    * The realm to use for the basic http auth
    */
@@ -92,8 +104,8 @@ public class AmbariAuthorizationFilter implements Filter {
             break;
           }
 
-          if (requestURI.matches("/api/v[0-9]+/clusters.*")) {
             // clusters require permission
+	  if (requestURI.matches(API_CLUSTERS_ALL_PATTERN)) {
             if (permissionId.equals(PermissionEntity.CLUSTER_READ_PERMISSION) ||
                 permissionId.equals(PermissionEntity.CLUSTER_OPERATE_PERMISSION)) {
               authorized = true;
@@ -105,13 +117,13 @@ public class AmbariAuthorizationFilter implements Filter {
               authorized = true;
               break;
             }
-          } else if (requestURI.matches("/api/v[0-9]+/views.*")) {
+	  } else if (requestURI.matches(API_VIEWS_ALL_PATTERN)) {
             // views require permission
             if (permissionId.equals(PermissionEntity.VIEW_USE_PERMISSION)) {
               authorized = true;
               break;
             }
-          } else if (requestURI.matches("/api/v[0-9]+/persist.*")) {
+          } else if (requestURI.matches(API_PERSIST_ALL_PATTERN)) {
             if (permissionId.equals(PermissionEntity.CLUSTER_OPERATE_PERMISSION)) {
               authorized = true;
               break;
@@ -120,14 +132,26 @@ public class AmbariAuthorizationFilter implements Filter {
         }
       }
 
-      if (!authorized && requestURI.matches(ViewInstanceEntity.VIEWS_CONTEXT_PATH_PATTERN)) {
-        final ViewInstanceVersionDTO dto = ViewInstanceEntity.parseContextPath(requestURI);
-        authorized = ViewRegistry.getInstance().checkPermission(dto.getViewName(), dto.getVersion(), dto.getInstanceName(), true);
+      if (!authorized && requestURI.matches(VIEWS_CONTEXT_PATH_PATTERN)) {
+        final ViewInstanceVersionDTO dto = parseViewInstanceInfo(requestURI);
+        authorized = getViewRegistry().checkPermission(dto.getViewName(), dto.getVersion(), dto.getInstanceName(), true);
       }
 
-      // allow GET for everything except views
+      // allow all types of requests for /users/{current_user}
+      if (!authorized && requestURI.matches(API_USERS_USERNAME_PATTERN)) {
+        final SecurityContext securityContext = getSecurityContext();
+        final String currentUserName = securityContext.getAuthentication().getName();
+        final String urlUserName = parseUserName(requestURI);
+        authorized = currentUserName.equalsIgnoreCase(urlUserName);
+      }
+
+      // allow GET for everything except /views, /api/v1/users, /api/v1/groups, /api/v1/ldap_sync_events
       if (!authorized &&
-          (!httpRequest.getMethod().equals("GET") || requestURI.matches("/views.*"))) {
+          (!httpRequest.getMethod().equals("GET")
+              || requestURI.matches(VIEWS_CONTEXT_ALL_PATTERN)
+              || requestURI.matches(API_USERS_ALL_PATTERN)
+              || requestURI.matches(API_GROUPS_ALL_PATTERN)
+              || requestURI.matches(API_LDAP_SYNC_EVENTS_ALL_PATTERN))) {
 
         httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
         httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "You do not have permissions to access this resource.");
@@ -166,7 +190,46 @@ public class AmbariAuthorizationFilter implements Filter {
     return value == null || value.length() == 0 ? defaultValue : value;
   }
 
+  /**
+   * Parses context path into view name, version and instance name
+   *
+   * @param contextPath the context path
+   * @return null if context path doesn't match correct pattern
+   */
+  static ViewInstanceVersionDTO parseViewInstanceInfo(String contextPath) {
+    final Pattern pattern = Pattern.compile(VIEWS_CONTEXT_PATH_PATTERN);
+    final Matcher matcher = pattern.matcher(contextPath);
+    if (!matcher.matches()) {
+      return null;
+    } else {
+      final String viewName = matcher.group(1);
+      final String version = matcher.group(2);
+      final String instanceName = matcher.group(3);
+      return new ViewInstanceVersionDTO(viewName, version, instanceName);
+    }
+  }
+
+  /**
+   * Parses url to get user name.
+   *
+   * @param url the url
+   * @return null if url doesn't match correct pattern
+   */
+  static String parseUserName(String url) {
+    final Pattern pattern = Pattern.compile(API_USERS_USERNAME_PATTERN);
+    final Matcher matcher = pattern.matcher(url);
+    if (!matcher.matches()) {
+      return null;
+    } else {
+      return matcher.group(1);
+    }
+  }
+
   SecurityContext getSecurityContext() {
     return SecurityContextHolder.getContext();
   }
+
+  ViewRegistry getViewRegistry() {
+    return ViewRegistry.getInstance();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
index 26daa1b..1cd3fc8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
@@ -24,7 +24,6 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.persistence.EntityManager;
 
 import org.apache.ambari.server.AmbariException;
@@ -66,7 +65,7 @@ import com.google.inject.persist.Transactional;
 @Singleton
 public class Users {
 
-  private final static Logger LOG = LoggerFactory.getLogger(Users.class);
+  private static final Logger LOG = LoggerFactory.getLogger(Users.class);
 
   @Inject
   Provider<EntityManager> entityManagerProvider;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
index c0545da..08aea6e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
@@ -20,8 +20,8 @@ package org.apache.ambari.server.orm.entities;
 
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
 import org.apache.ambari.server.security.SecurityHelper;
+import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
 import org.apache.ambari.server.view.ViewRegistryTest;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.server.view.configuration.InstanceConfigTest;
@@ -295,26 +295,11 @@ public class ViewInstanceEntityTest {
   public void testContextPath() throws Exception {
     ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
 
-    Assert.assertEquals(ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
+    Assert.assertEquals(AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
         viewInstanceDefinition.getContextPath());
   }
 
   @Test
-  public void testParseContextPath() throws Exception {
-    final String[] pathesToTest = {
-        ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
-        ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/index.html",
-        ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/api/test"
-    };
-    for (String contextPath: pathesToTest) {
-      final ViewInstanceVersionDTO dto = ViewInstanceEntity.parseContextPath(contextPath);
-      Assert.assertEquals("INSTANCE1", dto.getInstanceName());
-      Assert.assertEquals("MY_VIEW", dto.getViewName());
-      Assert.assertEquals("1.0.0", dto.getVersion());
-    }
-  }
-
-  @Test
   public void testInstanceData() throws Exception {
     TestSecurityHelper securityHelper = new TestSecurityHelper("user1");
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
index a950eb6..116b6ec 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
@@ -18,23 +18,40 @@
 
 package org.apache.ambari.server.security.authorization;
 
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.Assert;
+
 import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
+import org.apache.ambari.server.view.ViewRegistry;
 import org.easymock.EasyMock;
-import org.junit.BeforeClass;
+import org.easymock.IAnswer;
 import org.junit.Test;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.context.SecurityContext;
 
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.easymock.EasyMock.*;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import com.google.common.collect.Table.Cell;
 
 public class AmbariAuthorizationFilterTest {
 
@@ -121,4 +138,235 @@ public class AmbariAuthorizationFilterTest {
     verify(request, response, chain, filter, securityContext, authentication, authority,
         privilegeEntity, permission, filterConfig);
   }
+
+  @Test
+  public void testDoFilter_adminAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  true);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", true);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", true);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", true);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", true);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", true);
+    urlTests.put("/api/v1/users/user2", "POST", true);
+    urlTests.put("/api/v1/groups", "GET", true);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", true);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", true);
+
+    performGeneralDoFilterTest("admin", new int[] {PermissionEntity.AMBARI_ADMIN_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_clusterViewerAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  true);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", false);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", false);
+    urlTests.put("/api/v1/users/user2", "POST", false);
+    urlTests.put("/api/v1/groups", "GET", false);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user1", new int[] {PermissionEntity.CLUSTER_READ_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_clusterOperatorAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  true);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", false);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", false);
+    urlTests.put("/api/v1/users/user2", "POST", false);
+    urlTests.put("/api/v1/groups", "GET", false);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user1", new int[] {PermissionEntity.CLUSTER_OPERATE_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_viewUserAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  false);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", true);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", true);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", false);
+    urlTests.put("/api/v1/users/user2", "POST", false);
+    urlTests.put("/api/v1/groups", "GET", false);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user1", new int[] {PermissionEntity.VIEW_USE_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_userNoPermissionsAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  false);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", false);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", false);
+    urlTests.put("/api/v1/users/user1", "POST", false);
+    urlTests.put("/api/v1/users/user2", "GET", true);
+    urlTests.put("/api/v1/users/user2", "POST", true);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user2", new int[0], urlTests);
+  }
+
+  /**
+   * Creates mocks with given permissions and performs all given url tests.
+   *
+   * @param username user name
+   * @param permissionsGranted array of user permissions
+   * @param urlTests map of triples: url - http method - is allowed
+   * @throws Exception
+   */
+  private void performGeneralDoFilterTest(String username, final int[] permissionsGranted, Table<String, String, Boolean> urlTests) throws Exception {
+    final SecurityContext securityContext = createNiceMock(SecurityContext.class);
+    final Authentication authentication = createNiceMock(Authentication.class);
+    final FilterConfig filterConfig = createNiceMock(FilterConfig.class);
+    final AmbariAuthorizationFilter filter = createMockBuilder(AmbariAuthorizationFilter.class)
+        .addMockedMethod("getSecurityContext").addMockedMethod("getViewRegistry").withConstructor().createMock();
+    final List<AmbariGrantedAuthority> authorities = new ArrayList<AmbariGrantedAuthority>();
+    final ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
+
+    for (int permissionGranted: permissionsGranted) {
+      final AmbariGrantedAuthority authority = createNiceMock(AmbariGrantedAuthority.class);
+      final PrivilegeEntity privilegeEntity = createNiceMock(PrivilegeEntity.class);
+      final PermissionEntity permission = createNiceMock(PermissionEntity.class);
+
+      expect(authority.getPrivilegeEntity()).andReturn(privilegeEntity).anyTimes();
+      expect(privilegeEntity.getPermission()).andReturn(permission).anyTimes();
+      expect(permission.getId()).andReturn(permissionGranted).anyTimes();
+
+      replay(authority, privilegeEntity, permission);
+      authorities.add(authority);
+    }
+
+    EasyMock.<Collection<? extends GrantedAuthority>>expect(authentication.getAuthorities()).andReturn(authorities).anyTimes();
+    expect(filterConfig.getInitParameter("realm")).andReturn("AuthFilter").anyTimes();
+    expect(authentication.isAuthenticated()).andReturn(true).anyTimes();
+    expect(authentication.getName()).andReturn(username).anyTimes();
+    expect(filter.getSecurityContext()).andReturn(securityContext).anyTimes();
+    expect(filter.getViewRegistry()).andReturn(viewRegistry).anyTimes();
+    expect(securityContext.getAuthentication()).andReturn(authentication).anyTimes();
+    expect(viewRegistry.checkPermission(EasyMock.eq("AllowedView"), EasyMock.<String>anyObject(), EasyMock.<String>anyObject(), EasyMock.anyBoolean())).andAnswer(new IAnswer<Boolean>() {
+      @Override
+      public Boolean answer() throws Throwable {
+        for (int permissionGranted: permissionsGranted) {
+          if (permissionGranted == PermissionEntity.VIEW_USE_PERMISSION) {
+            return true;
+          }
+        }
+        return false;
+      }
+    }).anyTimes();
+    expect(viewRegistry.checkPermission(EasyMock.eq("DeniedView"), EasyMock.<String>anyObject(), EasyMock.<String>anyObject(), EasyMock.anyBoolean())).andReturn(false).anyTimes();
+
+    replay(authentication, filterConfig, filter, securityContext, viewRegistry);
+
+    for (final Cell<String, String, Boolean> urlTest: urlTests.cellSet()) {
+      final FilterChain chain = EasyMock.createStrictMock(FilterChain.class);
+      final HttpServletRequest request = createNiceMock(HttpServletRequest.class);
+      final HttpServletResponse response = createNiceMock(HttpServletResponse.class);
+
+      expect(request.getRequestURI()).andReturn(urlTest.getRowKey()).anyTimes();
+      expect(request.getMethod()).andReturn(urlTest.getColumnKey()).anyTimes();
+      if (urlTest.getValue()) {
+        chain.doFilter(EasyMock.<ServletRequest>anyObject(), EasyMock.<ServletResponse>anyObject());
+        EasyMock.expectLastCall().once();
+      }
+
+      replay(request, response, chain);
+
+      try {
+        filter.doFilter(request, response, chain);
+      } catch (AssertionError error) {
+        throw new Exception("doFilter() should not be chained on " + urlTest.getColumnKey() + " " + urlTest.getRowKey(), error);
+      }
+
+      try {
+        verify(chain);
+      } catch (AssertionError error) {
+        throw new Exception("verify( failed on " + urlTest.getColumnKey() + " " + urlTest.getRowKey(), error);
+      }
+    }
+  }
+
+  @Test
+  public void testParseUserName() throws Exception {
+    final String[] pathesToTest = {
+        "/api/v1/users/user",
+        "/api/v1/users/user?fields=*",
+        "/api/v22/users/user?fields=*"
+    };
+    for (String contextPath: pathesToTest) {
+      final String username = AmbariAuthorizationFilter.parseUserName(contextPath);
+      Assert.assertEquals("user", username);
+    }
+  }
+
+  @Test
+  public void testParseViewContextPath() throws Exception {
+    final String[] pathesToTest = {
+        AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
+        AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/index.html",
+        AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/api/test"
+    };
+    for (String contextPath: pathesToTest) {
+      final ViewInstanceVersionDTO dto = AmbariAuthorizationFilter.parseViewInstanceInfo(contextPath);
+      Assert.assertEquals("INSTANCE1", dto.getInstanceName());
+      Assert.assertEquals("MY_VIEW", dto.getViewName());
+      Assert.assertEquals("1.0.0", dto.getVersion());
+    }
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
index 5487db8..dbdb469 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
@@ -313,4 +313,5 @@ public class TestUsers {
 
     userDAO.merge(ldapUser);
   }
+
 }