diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
index eb3afeaa74d..8b791f60015 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
@@ -3100,6 +3100,13 @@ public static boolean areNodeLabelsEnabled(
public static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS =
NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "opts";
+ /*
+ * Support to view apps for given user in secure cluster.
+ */
+ public static final String DISPLAY_APPS_FOR_LOGGED_IN_USER =
+ RM_PREFIX + "display.per-user-apps";
+ public static final boolean DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER = false;
+
// RM and NM CSRF props
public static final String REST_CSRF = "webapp.rest-csrf.";
public static final String RM_CSRF_PREFIX = RM_PREFIX + REST_CSRF;
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
index afde222c54b..c2434e707a6 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
@@ -3297,4 +3297,13 @@
false
+
+ yarn.resourcemanager.display.per-user-apps
+ false
+
+ Flag to enable display of applications per user as an admin
+ configuration.
+
+
+
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java
index df3889313ee..d08005e64e0 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java
@@ -207,6 +207,8 @@
private ReservationSystem reservationSystem;
private ReservationInputValidator rValidator;
+ private boolean displayPerUserApps = false;
+
private static final EnumSet ACTIVE_APP_STATES = EnumSet.of(
RMAppState.ACCEPTED, RMAppState.RUNNING);
@@ -264,7 +266,11 @@ protected void serviceStart() throws Exception {
}
refreshServiceAcls(conf, RMPolicyProvider.getInstance());
}
-
+
+ this.displayPerUserApps = conf.getBoolean(
+ YarnConfiguration.DISPLAY_APPS_FOR_LOGGED_IN_USER,
+ YarnConfiguration.DEFAULT_DISPLAY_APPS_FOR_LOGGED_IN_USER);
+
this.server.start();
clientBindAddress = conf.updateConnectAddr(YarnConfiguration.RM_BIND_HOST,
YarnConfiguration.RM_ADDRESS,
@@ -898,6 +904,12 @@ public void remove() {
continue;
}
+ // Given RM is configured to display apps per user, skip apps to which
+ // this caller doesn't have access to view.
+ if (displayPerUserApps && !allowAccess) {
+ continue;
+ }
+
reports.add(application.createAndGetApplicationReport(
callerUGI.getUserName(), allowAccess));
}
@@ -1766,4 +1778,9 @@ private RMApp verifyUserAccessForRMApp(ApplicationId applicationId,
return application;
}
+ @VisibleForTesting
+ public void setDisplayPerUserApps(boolean displayPerUserApps) {
+ this.displayPerUserApps = displayPerUserApps;
+ }
+
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java
index ea733a4ce4a..1e4bfbdcfe8 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java
@@ -1118,6 +1118,12 @@ public void handle(Event event) {}
assertEquals("Incorrect number of applications for user", 3,
rmService.getApplications(request).getApplicationList().size());
+ rmService.setDisplayPerUserApps(true);
+ userSet.clear();
+ assertEquals("Incorrect number of applications for user", 6,
+ rmService.getApplications(request).getApplicationList().size());
+ rmService.setDisplayPerUserApps(false);
+
// Check tags
request = GetApplicationsRequest.newInstance(
ApplicationsRequestScope.ALL, null, null, null, null, null, null,
@@ -2061,4 +2067,72 @@ protected ClientRMService createClientRMService() {
rpc.stopProxy(client, conf);
new File(excludeFile).delete();
}
+
+ @Test
+ public void testGetApplicationsWithPerUserApps()
+ throws IOException, YarnException {
+ /*
+ * Submit 3 applications alternately in two queues
+ */
+ // Basic setup
+ YarnScheduler yarnScheduler = mockYarnScheduler();
+ RMContext rmContext = mock(RMContext.class);
+ mockRMContext(yarnScheduler, rmContext);
+ RMStateStore stateStore = mock(RMStateStore.class);
+ when(rmContext.getStateStore()).thenReturn(stateStore);
+ doReturn(mock(RMTimelineCollectorManager.class)).when(rmContext)
+ .getRMTimelineCollectorManager();
+
+ RMAppManager appManager = new RMAppManager(rmContext, yarnScheduler, null,
+ mock(ApplicationACLsManager.class), new Configuration());
+ when(rmContext.getDispatcher().getEventHandler())
+ .thenReturn(new EventHandler() {
+ public void handle(Event event) {
+ }
+ });
+
+ // Simulate Queue ACL manager which returns false always
+ QueueACLsManager queueAclsManager = mock(QueueACLsManager.class);
+ when(queueAclsManager.checkAccess(any(UserGroupInformation.class),
+ any(QueueACL.class), any(RMApp.class), any(String.class),
+ anyListOf(String.class))).thenReturn(false);
+
+ // Simulate app ACL manager which returns false always
+ ApplicationACLsManager appAclsManager = mock(ApplicationACLsManager.class);
+ when(appAclsManager.checkAccess(eq(UserGroupInformation.getCurrentUser()),
+ any(ApplicationAccessType.class), any(String.class),
+ any(ApplicationId.class))).thenReturn(false);
+ ClientRMService rmService = new ClientRMService(rmContext, yarnScheduler,
+ appManager, appAclsManager, queueAclsManager, null);
+ rmService.init(new Configuration());
+
+ // Initialize appnames and queues
+ String[] queues = {QUEUE_1, QUEUE_2};
+ String[] appNames = {MockApps.newAppName(), MockApps.newAppName(),
+ MockApps.newAppName()};
+ ApplicationId[] appIds = {getApplicationId(101), getApplicationId(102),
+ getApplicationId(103)};
+ List tags = Arrays.asList("Tag1", "Tag2", "Tag3");
+
+ long[] submitTimeMillis = new long[3];
+ // Submit applications
+ for (int i = 0; i < appIds.length; i++) {
+ ApplicationId appId = appIds[i];
+ SubmitApplicationRequest submitRequest = mockSubmitAppRequest(appId,
+ appNames[i], queues[i % queues.length],
+ new HashSet(tags.subList(0, i + 1)));
+ rmService.submitApplication(submitRequest);
+ submitTimeMillis[i] = System.currentTimeMillis();
+ }
+
+ // Test different cases of ClientRMService#getApplications()
+ GetApplicationsRequest request = GetApplicationsRequest.newInstance();
+ assertEquals("Incorrect total number of apps", 6,
+ rmService.getApplications(request).getApplicationList().size());
+
+ rmService.setDisplayPerUserApps(true);
+ assertEquals("Incorrect number of applications for user", 0,
+ rmService.getApplications(request).getApplicationList().size());
+ rmService.setDisplayPerUserApps(false);
+ }
}