YARN-7157. Add admin configuration to filter per-user's apps in secure cluster. Contributed by Sunil G.
This commit is contained in:
parent
61f41b071d
commit
c570ddaa66
|
@ -2936,6 +2936,13 @@ public class YarnConfiguration extends Configuration {
|
||||||
public static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS =
|
public static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS =
|
||||||
NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "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
|
// RM and NM CSRF props
|
||||||
public static final String REST_CSRF = "webapp.rest-csrf.";
|
public static final String REST_CSRF = "webapp.rest-csrf.";
|
||||||
public static final String RM_CSRF_PREFIX = RM_PREFIX + REST_CSRF;
|
public static final String RM_CSRF_PREFIX = RM_PREFIX + REST_CSRF;
|
||||||
|
|
|
@ -3183,4 +3183,13 @@
|
||||||
<value>0.0.0.0:8091</value>
|
<value>0.0.0.0:8091</value>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property>
|
||||||
|
<name>yarn.resourcemanager.display.per-user-apps</name>
|
||||||
|
<value>false</value>
|
||||||
|
<description>
|
||||||
|
Flag to enable display of applications per user as an admin
|
||||||
|
configuration.
|
||||||
|
</description>
|
||||||
|
</property>
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -205,6 +205,8 @@ public class ClientRMService extends AbstractService implements
|
||||||
private ReservationSystem reservationSystem;
|
private ReservationSystem reservationSystem;
|
||||||
private ReservationInputValidator rValidator;
|
private ReservationInputValidator rValidator;
|
||||||
|
|
||||||
|
private boolean displayPerUserApps = false;
|
||||||
|
|
||||||
private static final EnumSet<RMAppState> ACTIVE_APP_STATES = EnumSet.of(
|
private static final EnumSet<RMAppState> ACTIVE_APP_STATES = EnumSet.of(
|
||||||
RMAppState.ACCEPTED, RMAppState.RUNNING);
|
RMAppState.ACCEPTED, RMAppState.RUNNING);
|
||||||
|
|
||||||
|
@ -263,6 +265,10 @@ public class ClientRMService extends AbstractService implements
|
||||||
refreshServiceAcls(conf, RMPolicyProvider.getInstance());
|
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();
|
this.server.start();
|
||||||
clientBindAddress = conf.updateConnectAddr(YarnConfiguration.RM_BIND_HOST,
|
clientBindAddress = conf.updateConnectAddr(YarnConfiguration.RM_BIND_HOST,
|
||||||
YarnConfiguration.RM_ADDRESS,
|
YarnConfiguration.RM_ADDRESS,
|
||||||
|
@ -881,6 +887,12 @@ public class ClientRMService extends AbstractService implements
|
||||||
continue;
|
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(
|
reports.add(application.createAndGetApplicationReport(
|
||||||
callerUGI.getUserName(), allowAccess));
|
callerUGI.getUserName(), allowAccess));
|
||||||
}
|
}
|
||||||
|
@ -1729,4 +1741,9 @@ public class ClientRMService extends AbstractService implements
|
||||||
return application;
|
return application;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void setDisplayPerUserApps(boolean displayPerUserApps) {
|
||||||
|
this.displayPerUserApps = displayPerUserApps;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.anyBoolean;
|
import static org.mockito.Matchers.anyBoolean;
|
||||||
|
import static org.mockito.Matchers.anyListOf;
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -853,6 +854,12 @@ public class TestClientRMService {
|
||||||
assertEquals("Incorrect number of applications for user", 3,
|
assertEquals("Incorrect number of applications for user", 3,
|
||||||
rmService.getApplications(request).getApplicationList().size());
|
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
|
// Check tags
|
||||||
request = GetApplicationsRequest.newInstance(
|
request = GetApplicationsRequest.newInstance(
|
||||||
ApplicationsRequestScope.ALL, null, null, null, null, null, null,
|
ApplicationsRequestScope.ALL, null, null, null, null, null, null,
|
||||||
|
@ -1793,4 +1800,70 @@ public class TestClientRMService {
|
||||||
rpc.stopProxy(client, conf);
|
rpc.stopProxy(client, conf);
|
||||||
new File(excludeFile).delete();
|
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);
|
||||||
|
|
||||||
|
RMAppManager appManager = new RMAppManager(rmContext, yarnScheduler, null,
|
||||||
|
mock(ApplicationACLsManager.class), new Configuration());
|
||||||
|
when(rmContext.getDispatcher().getEventHandler())
|
||||||
|
.thenReturn(new EventHandler<Event>() {
|
||||||
|
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<String> 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<String>(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue