YARN-10035. Add ability to filter the Cluster Applications API request by name. Contributed by Adam Antal

This commit is contained in:
Szilard Nemeth 2020-01-06 16:26:33 +01:00
parent 4a76ab777f
commit 768ee22e9e
21 changed files with 95 additions and 20 deletions

View File

@ -393,4 +393,22 @@ public abstract class GetApplicationsRequest {
@Private @Private
@Unstable @Unstable
public abstract void setScope(ApplicationsRequestScope scope); public abstract void setScope(ApplicationsRequestScope scope);
/**
* Set the name to filter applications.
*
* @return the name
*/
@Private
@Unstable
public abstract String getName();
/**
* Get the name to filter applications.
*
* @param name of the application
*/
@Private
@Unstable
public abstract void setName(String name);
} }

View File

@ -206,6 +206,7 @@ message GetApplicationsRequestProto {
optional int64 finish_end = 9; optional int64 finish_end = 9;
repeated string applicationTags = 10; repeated string applicationTags = 10;
optional ApplicationsRequestScopeProto scope = 11 [default = ALL]; optional ApplicationsRequestScopeProto scope = 11 [default = ALL];
optional string name = 12;
} }
message GetApplicationsResponseProto { message GetApplicationsResponseProto {

View File

@ -55,6 +55,7 @@ public class GetApplicationsRequestPBImpl extends GetApplicationsRequest {
Range<Long> finish = null; Range<Long> finish = null;
private Set<String> applicationTags; private Set<String> applicationTags;
private ApplicationsRequestScope scope; private ApplicationsRequestScope scope;
private String name;
public GetApplicationsRequestPBImpl() { public GetApplicationsRequestPBImpl() {
builder = GetApplicationsRequestProto.newBuilder(); builder = GetApplicationsRequestProto.newBuilder();
@ -121,6 +122,9 @@ public class GetApplicationsRequestPBImpl extends GetApplicationsRequest {
builder.clearQueues(); builder.clearQueues();
builder.addAllQueues(queues); builder.addAllQueues(queues);
} }
if (name != null) {
builder.setName(name);
}
} }
private void maybeInitBuilder() { private void maybeInitBuilder() {
@ -370,6 +374,27 @@ public class GetApplicationsRequestPBImpl extends GetApplicationsRequest {
this.finish = Range.between(begin, end); this.finish = Range.between(begin, end);
} }
@Override
public synchronized String getName() {
GetApplicationsRequestProtoOrBuilder p = viaProto ? proto : builder;
if (this.name != null) {
return this.name;
}
if (p.hasName()) {
this.name = p.getName();
}
return this.name;
}
@Override
public synchronized void setName(String name) {
maybeInitBuilder();
if (name == null) {
builder.clearName();
}
this.name = name;
}
@Override @Override
public int hashCode() { public int hashCode() {
return getProto().hashCode(); return getProto().hashCode();

View File

@ -107,7 +107,8 @@ public class AHSWebServices extends WebServices {
public AppsInfo get(@Context HttpServletRequest req, public AppsInfo get(@Context HttpServletRequest req,
@Context HttpServletResponse res) { @Context HttpServletResponse res) {
return getApps(req, res, null, Collections.<String> emptySet(), null, null, return getApps(req, res, null, Collections.<String> emptySet(), null, null,
null, null, null, null, null, null, Collections.<String> emptySet()); null, null, null, null, null, null, null,
Collections.<String> emptySet());
} }
@GET @GET
@ -126,12 +127,13 @@ public class AHSWebServices extends WebServices {
@QueryParam("startedTimeEnd") String startedEnd, @QueryParam("startedTimeEnd") String startedEnd,
@QueryParam("finishedTimeBegin") String finishBegin, @QueryParam("finishedTimeBegin") String finishBegin,
@QueryParam("finishedTimeEnd") String finishEnd, @QueryParam("finishedTimeEnd") String finishEnd,
@QueryParam("name") String name,
@QueryParam("applicationTypes") Set<String> applicationTypes) { @QueryParam("applicationTypes") Set<String> applicationTypes) {
initForReadableEndpoints(res); initForReadableEndpoints(res);
validateStates(stateQuery, statesQuery); validateStates(stateQuery, statesQuery);
return super.getApps(req, res, stateQuery, statesQuery, finalStatusQuery, return super.getApps(req, res, stateQuery, statesQuery, finalStatusQuery,
userQuery, queueQuery, count, startedBegin, startedEnd, finishBegin, userQuery, queueQuery, count, startedBegin, startedEnd, finishBegin,
finishEnd, applicationTypes); finishEnd, name, applicationTypes);
} }
@GET @GET

View File

@ -75,7 +75,7 @@ public class WebServices {
public AppsInfo getApps(HttpServletRequest req, HttpServletResponse res, public AppsInfo getApps(HttpServletRequest req, HttpServletResponse res,
String stateQuery, Set<String> statesQuery, String finalStatusQuery, String stateQuery, Set<String> statesQuery, String finalStatusQuery,
String userQuery, String queueQuery, String count, String startedBegin, String userQuery, String queueQuery, String count, String startedBegin,
String startedEnd, String finishBegin, String finishEnd, String startedEnd, String finishBegin, String finishEnd, String nameQuery,
Set<String> applicationTypes) { Set<String> applicationTypes) {
UserGroupInformation callerUGI = getUser(req); UserGroupInformation callerUGI = getUser(req);
boolean checkEnd = false; boolean checkEnd = false;
@ -207,6 +207,11 @@ public class WebServices {
&& (appReport.getFinishTime() < fBegin || appReport.getFinishTime() > fEnd)) { && (appReport.getFinishTime() < fBegin || appReport.getFinishTime() > fEnd)) {
continue; continue;
} }
if (nameQuery != null && !nameQuery.equals(appReport.getName())) {
continue;
}
AppInfo app = new AppInfo(appReport); AppInfo app = new AppInfo(appReport);
allApps.add(app); allApps.add(app);

View File

@ -865,6 +865,7 @@ public class ClientRMService extends AbstractService implements
Range<Long> start = request.getStartRange(); Range<Long> start = request.getStartRange();
Range<Long> finish = request.getFinishRange(); Range<Long> finish = request.getFinishRange();
ApplicationsRequestScope scope = request.getScope(); ApplicationsRequestScope scope = request.getScope();
String name = request.getName();
final Map<ApplicationId, RMApp> apps = rmContext.getRMApps(); final Map<ApplicationId, RMApp> apps = rmContext.getRMApps();
Iterator<RMApp> appsIter = apps.values().iterator(); Iterator<RMApp> appsIter = apps.values().iterator();
@ -943,6 +944,10 @@ public class ClientRMService extends AbstractService implements
continue; continue;
} }
if (name != null && !name.equals(application.getName())) {
continue;
}
reports.add(application.createAndGetApplicationReport( reports.add(application.createAndGetApplicationReport(
callerUGI.getUserName(), allowAccess)); callerUGI.getUserName(), allowAccess));
} }

View File

@ -44,6 +44,7 @@ public class ApplicationsRequestBuilder {
private long finishTimeEnd = Long.MAX_VALUE; private long finishTimeEnd = Long.MAX_VALUE;
private Set<String> appTypes = Sets.newHashSet(); private Set<String> appTypes = Sets.newHashSet();
private Set<String> appTags = Sets.newHashSet(); private Set<String> appTags = Sets.newHashSet();
private String name = null;
private ResourceManager rm; private ResourceManager rm;
private ApplicationsRequestBuilder() { private ApplicationsRequestBuilder() {
@ -137,6 +138,11 @@ public class ApplicationsRequestBuilder {
return this; return this;
} }
public ApplicationsRequestBuilder withName(String applicationName) {
name = applicationName;
return this;
}
private void validate() { private void validate() {
queues.forEach(q -> validateQueueExists(rm, q)); queues.forEach(q -> validateQueueExists(rm, q));
validateLimit(); validateLimit();
@ -225,6 +231,9 @@ public class ApplicationsRequestBuilder {
if (!appTags.isEmpty()) { if (!appTags.isEmpty()) {
request.setApplicationTags(appTags); request.setApplicationTags(appTags);
} }
if (name != null) {
request.setName(name);
}
return request; return request;
} }

View File

@ -245,6 +245,7 @@ public final class RMWSConsts {
public static final String COMMAND = "command"; public static final String COMMAND = "command";
public static final String ACTIONS = "actions"; public static final String ACTIONS = "actions";
public static final String SUMMARIZE = "summarize"; public static final String SUMMARIZE = "summarize";
public static final String NAME = "name";
private RMWSConsts() { private RMWSConsts() {
// not called // not called

View File

@ -186,6 +186,7 @@ public interface RMWebServiceProtocol {
* @param finishEnd filter the result by finish end time. It is a QueryParam. * @param finishEnd filter the result by finish end time. It is a QueryParam.
* @param applicationTypes filter the result by types. It is a QueryParam. * @param applicationTypes filter the result by types. It is a QueryParam.
* @param applicationTags filter the result by tags. It is a QueryParam. * @param applicationTags filter the result by tags. It is a QueryParam.
* @param name filter the name of the application. It is a QueryParam.
* @param unselectedFields De-selected params to avoid from report. It is a * @param unselectedFields De-selected params to avoid from report. It is a
* QueryParam. * QueryParam.
* @return all apps in the cluster * @return all apps in the cluster
@ -195,7 +196,7 @@ public interface RMWebServiceProtocol {
Set<String> statesQuery, String finalStatusQuery, String userQuery, Set<String> statesQuery, String finalStatusQuery, String userQuery,
String queueQuery, String count, String startedBegin, String startedEnd, String queueQuery, String count, String startedBegin, String startedEnd,
String finishBegin, String finishEnd, Set<String> applicationTypes, String finishBegin, String finishEnd, Set<String> applicationTypes,
Set<String> applicationTags, Set<String> unselectedFields); Set<String> applicationTags, String name, Set<String> unselectedFields);
/** /**
* This method retrieve all the activities in a specific node, and it is * This method retrieve all the activities in a specific node, and it is

View File

@ -610,6 +610,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol {
@QueryParam(RMWSConsts.FINISHED_TIME_END) String finishEnd, @QueryParam(RMWSConsts.FINISHED_TIME_END) String finishEnd,
@QueryParam(RMWSConsts.APPLICATION_TYPES) Set<String> applicationTypes, @QueryParam(RMWSConsts.APPLICATION_TYPES) Set<String> applicationTypes,
@QueryParam(RMWSConsts.APPLICATION_TAGS) Set<String> applicationTags, @QueryParam(RMWSConsts.APPLICATION_TAGS) Set<String> applicationTags,
@QueryParam(RMWSConsts.NAME) String name,
@QueryParam(RMWSConsts.DESELECTS) Set<String> unselectedFields) { @QueryParam(RMWSConsts.DESELECTS) Set<String> unselectedFields) {
initForReadableEndpoints(); initForReadableEndpoints();
@ -627,6 +628,7 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol {
.withFinishTimeEnd(finishEnd) .withFinishTimeEnd(finishEnd)
.withApplicationTypes(applicationTypes) .withApplicationTypes(applicationTypes)
.withApplicationTags(applicationTags) .withApplicationTags(applicationTags)
.withName(name)
.build(); .build();
List<ApplicationReport> appReports; List<ApplicationReport> appReports;

View File

@ -703,12 +703,14 @@ public class TestRMWebServices extends JerseyTestBase {
// verify we don't get any apps when querying // verify we don't get any apps when querying
HttpServletRequest mockHsr = mock(HttpServletRequest.class); HttpServletRequest mockHsr = mock(HttpServletRequest.class);
AppsInfo appsInfo = webSvc.getApps(mockHsr, null, emptySet, null, AppsInfo appsInfo = webSvc.getApps(mockHsr, null, emptySet, null,
null, null, null, null, null, null, null, emptySet, emptySet, null); null, null, null, null, null, null, null, emptySet, emptySet, null,
null);
assertTrue(appsInfo.getApps().isEmpty()); assertTrue(appsInfo.getApps().isEmpty());
// verify we don't get an NPE when specifying a final status query // verify we don't get an NPE when specifying a final status query
appsInfo = webSvc.getApps(mockHsr, null, emptySet, "FAILED", appsInfo = webSvc.getApps(mockHsr, null, emptySet, "FAILED",
null, null, null, null, null, null, null, emptySet, emptySet, null); null, null, null, null, null, null, null, emptySet, emptySet, null,
null);
assertTrue(appsInfo.getApps().isEmpty()); assertTrue(appsInfo.getApps().isEmpty());
} }
@ -947,7 +949,8 @@ public class TestRMWebServices extends JerseyTestBase {
Set<String> emptySet = Collections.unmodifiableSet(Collections.emptySet()); Set<String> emptySet = Collections.unmodifiableSet(Collections.emptySet());
AppsInfo appsInfo = webSvc.getApps(mockHsr, null, emptySet, null, AppsInfo appsInfo = webSvc.getApps(mockHsr, null, emptySet, null,
null, null, null, null, null, null, null, emptySet, emptySet, null); null, null, null, null, null, null, null, emptySet, emptySet,
null, null);
assertEquals("Incorrect Number of Apps", 1, appsInfo.getApps().size()); assertEquals("Incorrect Number of Apps", 1, appsInfo.getApps().size());
assertEquals("Invalid XML Characters Present", assertEquals("Invalid XML Characters Present",

View File

@ -172,7 +172,7 @@ public class DefaultRequestInterceptorREST
Set<String> statesQuery, String finalStatusQuery, String userQuery, Set<String> statesQuery, String finalStatusQuery, String userQuery,
String queueQuery, String count, String startedBegin, String startedEnd, String queueQuery, String count, String startedBegin, String startedEnd,
String finishBegin, String finishEnd, Set<String> applicationTypes, String finishBegin, String finishEnd, Set<String> applicationTypes,
Set<String> applicationTags, Set<String> unselectedFields) { Set<String> applicationTags, String name, Set<String> unselectedFields) {
// all the params are specified inside hsr // all the params are specified inside hsr
return RouterWebServiceUtil.genericForward(webAppAddress, hsr, return RouterWebServiceUtil.genericForward(webAppAddress, hsr,
AppsInfo.class, HTTPMethods.GET, AppsInfo.class, HTTPMethods.GET,

View File

@ -672,7 +672,7 @@ public class FederationInterceptorREST extends AbstractRESTRequestInterceptor {
Set<String> statesQuery, String finalStatusQuery, String userQuery, Set<String> statesQuery, String finalStatusQuery, String userQuery,
String queueQuery, String count, String startedBegin, String startedEnd, String queueQuery, String count, String startedBegin, String startedEnd,
String finishBegin, String finishEnd, Set<String> applicationTypes, String finishBegin, String finishEnd, Set<String> applicationTypes,
Set<String> applicationTags, Set<String> unselectedFields) { Set<String> applicationTags, String name, Set<String> unselectedFields) {
AppsInfo apps = new AppsInfo(); AppsInfo apps = new AppsInfo();
long startTime = clock.getTime(); long startTime = clock.getTime();
@ -701,7 +701,7 @@ public class FederationInterceptorREST extends AbstractRESTRequestInterceptor {
AppsInfo rmApps = interceptor.getApps(hsrCopy, stateQuery, AppsInfo rmApps = interceptor.getApps(hsrCopy, stateQuery,
statesQuery, finalStatusQuery, userQuery, queueQuery, count, statesQuery, finalStatusQuery, userQuery, queueQuery, count,
startedBegin, startedEnd, finishBegin, finishEnd, startedBegin, startedEnd, finishBegin, finishEnd,
applicationTypes, applicationTags, unselectedFields); applicationTypes, applicationTags, name, unselectedFields);
if (rmApps == null) { if (rmApps == null) {
routerMetrics.incrMultipleAppsFailedRetrieved(); routerMetrics.incrMultipleAppsFailedRetrieved();

View File

@ -433,13 +433,14 @@ public class RouterWebServices implements RMWebServiceProtocol {
@QueryParam(RMWSConsts.FINISHED_TIME_END) String finishEnd, @QueryParam(RMWSConsts.FINISHED_TIME_END) String finishEnd,
@QueryParam(RMWSConsts.APPLICATION_TYPES) Set<String> applicationTypes, @QueryParam(RMWSConsts.APPLICATION_TYPES) Set<String> applicationTypes,
@QueryParam(RMWSConsts.APPLICATION_TAGS) Set<String> applicationTags, @QueryParam(RMWSConsts.APPLICATION_TAGS) Set<String> applicationTags,
@QueryParam(RMWSConsts.NAME) String name,
@QueryParam(RMWSConsts.DESELECTS) Set<String> unselectedFields) { @QueryParam(RMWSConsts.DESELECTS) Set<String> unselectedFields) {
init(); init();
RequestInterceptorChainWrapper pipeline = getInterceptorChain(hsr); RequestInterceptorChainWrapper pipeline = getInterceptorChain(hsr);
return pipeline.getRootInterceptor().getApps(hsr, stateQuery, statesQuery, return pipeline.getRootInterceptor().getApps(hsr, stateQuery, statesQuery,
finalStatusQuery, userQuery, queueQuery, count, startedBegin, finalStatusQuery, userQuery, queueQuery, count, startedBegin,
startedEnd, finishBegin, finishEnd, applicationTypes, applicationTags, startedEnd, finishBegin, finishEnd, applicationTypes, applicationTags,
unselectedFields); name, unselectedFields);
} }
@GET @GET

View File

@ -169,7 +169,8 @@ public abstract class BaseRouterWebServicesTest {
protected AppsInfo getApps(String user) protected AppsInfo getApps(String user)
throws IOException, InterruptedException { throws IOException, InterruptedException {
return routerWebService.getApps(createHttpServletRequest(user), null, null, return routerWebService.getApps(createHttpServletRequest(user), null, null,
null, null, null, null, null, null, null, null, null, null, null); null, null, null, null, null, null, null, null, null, null, null,
null);
} }
protected ActivitiesInfo getActivities(String user) protected ActivitiesInfo getActivities(String user)

View File

@ -117,7 +117,7 @@ public class MockDefaultRequestInterceptorREST
Set<String> statesQuery, String finalStatusQuery, String userQuery, Set<String> statesQuery, String finalStatusQuery, String userQuery,
String queueQuery, String count, String startedBegin, String startedEnd, String queueQuery, String count, String startedBegin, String startedEnd,
String finishBegin, String finishEnd, Set<String> applicationTypes, String finishBegin, String finishEnd, Set<String> applicationTypes,
Set<String> applicationTags, Set<String> unselectedFields) { Set<String> applicationTags, String name, Set<String> unselectedFields) {
if (!isRunning) { if (!isRunning) {
throw new RuntimeException("RM is stopped"); throw new RuntimeException("RM is stopped");
} }

View File

@ -128,7 +128,7 @@ public class MockRESTRequestInterceptor extends AbstractRESTRequestInterceptor {
Set<String> statesQuery, String finalStatusQuery, String userQuery, Set<String> statesQuery, String finalStatusQuery, String userQuery,
String queueQuery, String count, String startedBegin, String startedEnd, String queueQuery, String count, String startedBegin, String startedEnd,
String finishBegin, String finishEnd, Set<String> applicationTypes, String finishBegin, String finishEnd, Set<String> applicationTypes,
Set<String> applicationTags, Set<String> unselectedFields) { Set<String> applicationTags, String name, Set<String> unselectedFields) {
return new AppsInfo(); return new AppsInfo();
} }

View File

@ -153,11 +153,11 @@ public class PassThroughRESTRequestInterceptor
Set<String> statesQuery, String finalStatusQuery, String userQuery, Set<String> statesQuery, String finalStatusQuery, String userQuery,
String queueQuery, String count, String startedBegin, String startedEnd, String queueQuery, String count, String startedBegin, String startedEnd,
String finishBegin, String finishEnd, Set<String> applicationTypes, String finishBegin, String finishEnd, Set<String> applicationTypes,
Set<String> applicationTags, Set<String> unselectedFields) { Set<String> applicationTags, String name, Set<String> unselectedFields) {
return getNextInterceptor().getApps(hsr, stateQuery, statesQuery, return getNextInterceptor().getApps(hsr, stateQuery, statesQuery,
finalStatusQuery, userQuery, queueQuery, count, startedBegin, finalStatusQuery, userQuery, queueQuery, count, startedBegin,
startedEnd, finishBegin, finishEnd, applicationTypes, applicationTags, startedEnd, finishBegin, finishEnd, applicationTypes, applicationTags,
unselectedFields); name, unselectedFields);
} }
@Override @Override

View File

@ -391,7 +391,7 @@ public class TestFederationInterceptorREST extends BaseRouterWebServicesTest {
throws YarnException, IOException, InterruptedException { throws YarnException, IOException, InterruptedException {
AppsInfo responseGet = interceptor.getApps(null, null, null, null, null, AppsInfo responseGet = interceptor.getApps(null, null, null, null, null,
null, null, null, null, null, null, null, null, null); null, null, null, null, null, null, null, null, null, null);
Assert.assertNotNull(responseGet); Assert.assertNotNull(responseGet);
Assert.assertEquals(NUM_SUBCLUSTER, responseGet.getApps().size()); Assert.assertEquals(NUM_SUBCLUSTER, responseGet.getApps().size());

View File

@ -287,7 +287,7 @@ public class TestFederationInterceptorRESTRetry
setupCluster(Arrays.asList(bad2)); setupCluster(Arrays.asList(bad2));
AppsInfo response = interceptor.getApps(null, null, null, null, null, null, AppsInfo response = interceptor.getApps(null, null, null, null, null, null,
null, null, null, null, null, null, null, null); null, null, null, null, null, null, null, null, null);
Assert.assertNull(response); Assert.assertNull(response);
} }
@ -301,7 +301,7 @@ public class TestFederationInterceptorRESTRetry
setupCluster(Arrays.asList(bad1, bad2)); setupCluster(Arrays.asList(bad1, bad2));
AppsInfo response = interceptor.getApps(null, null, null, null, null, null, AppsInfo response = interceptor.getApps(null, null, null, null, null, null,
null, null, null, null, null, null, null, null); null, null, null, null, null, null, null, null, null);
Assert.assertNull(response); Assert.assertNull(response);
} }
@ -315,7 +315,7 @@ public class TestFederationInterceptorRESTRetry
setupCluster(Arrays.asList(good, bad2)); setupCluster(Arrays.asList(good, bad2));
AppsInfo response = interceptor.getApps(null, null, null, null, null, null, AppsInfo response = interceptor.getApps(null, null, null, null, null, null,
null, null, null, null, null, null, null, null); null, null, null, null, null, null, null, null, null);
Assert.assertNotNull(response); Assert.assertNotNull(response);
Assert.assertEquals(1, response.getApps().size()); Assert.assertEquals(1, response.getApps().size());
} }

View File

@ -1564,6 +1564,7 @@ Multiple parameters can be specified for GET operations. The started and finishe
* finishedTimeEnd - applications with finish time ending with this time, specified in ms since epoch * finishedTimeEnd - applications with finish time ending with this time, specified in ms since epoch
* applicationTypes - applications matching the given application types, specified as a comma-separated list. * applicationTypes - applications matching the given application types, specified as a comma-separated list.
* applicationTags - applications matching any of the given application tags, specified as a comma-separated list. * applicationTags - applications matching any of the given application tags, specified as a comma-separated list.
* name - name of the application
* deSelects - a generic fields which will be skipped in the result. * deSelects - a generic fields which will be skipped in the result.
### Elements of the *apps* (Applications) object ### Elements of the *apps* (Applications) object