diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ApplicationSubmissionContext.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ApplicationSubmissionContext.java index 529df11..1ee04f0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ApplicationSubmissionContext.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ApplicationSubmissionContext.java @@ -88,7 +88,7 @@ public static ApplicationSubmissionContext newInstance( int maxAppAttempts, Resource resource, String applicationType) { return newInstance(applicationId, applicationName, queue, priority, amContainer, isUnmanagedAM, cancelTokensWhenComplete, maxAppAttempts, - resource, null, false); + resource, applicationType, false); } @Public diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/GenericExceptionHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/GenericExceptionHandler.java index 74180f3..1e53e02 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/GenericExceptionHandler.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/GenericExceptionHandler.java @@ -21,10 +21,12 @@ import java.io.IOException; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; +import javax.xml.bind.UnmarshalException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -87,6 +89,9 @@ public Response toResponse(Exception e) { s = Response.Status.BAD_REQUEST; } else if (e instanceof BadRequestException) { s = Response.Status.BAD_REQUEST; + } else if (e instanceof WebApplicationException + && e.getCause() instanceof UnmarshalException) { + s = Response.Status.BAD_REQUEST; } else { LOG.warn("INTERNAL_SERVER_ERROR", e); s = Response.Status.INTERNAL_SERVER_ERROR; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java index 60fbfcd..bb20b2a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java @@ -19,6 +19,8 @@ package org.apache.hadoop.yarn.server.resourcemanager.webapp; import java.io.IOException; +import java.nio.ByteBuffer; +import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.Collection; import java.util.EnumSet; @@ -31,31 +33,51 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authorize.AuthorizationException; import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationsRequest; +import org.apache.hadoop.yarn.api.protocolrecords.GetNewApplicationRequest; +import org.apache.hadoop.yarn.api.protocolrecords.GetNewApplicationResponse; +import org.apache.hadoop.yarn.api.protocolrecords.KillApplicationRequest; +import org.apache.hadoop.yarn.api.protocolrecords.KillApplicationResponse; +import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest; +import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationResponse; import org.apache.hadoop.yarn.api.records.ApplicationAccessType; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationReport; +import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext; +import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; +import org.apache.hadoop.yarn.api.records.LocalResource; import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.api.records.NodeState; +import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.QueueACL; +import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.YarnApplicationState; +import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; import org.apache.hadoop.yarn.factories.RecordFactory; import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; +import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger; +import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants; import org.apache.hadoop.yarn.server.resourcemanager.RMServerUtils; import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; @@ -70,6 +92,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppAttemptInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppAttemptsInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppSubmissionInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ApplicationStatisticsInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppsInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.CapacitySchedulerInfo; @@ -77,6 +100,8 @@ import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterMetricsInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.FairSchedulerInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.FifoSchedulerInfo; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.LocalResourceInfo; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NewApplicationInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodeInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodesInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerInfo; @@ -90,6 +115,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; +import com.sun.jersey.core.util.Base64; @Singleton @Path("/ws/v1/cluster") @@ -590,4 +616,350 @@ public AppAttemptsInfo getAppAttempts(@PathParam("appid") String appId) { return appAttemptsInfo; } + + // can't return POJO because we can't control the status code + // it's always set to 200 when we need to allow it to be set + // to 202 + + @PUT + @Path("/apps/{appid}") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Response updateApp(AppInfo appInfo, @Context HttpServletRequest hsr, + @PathParam("appid") String appId) throws AuthorizationException, + YarnException, InterruptedException, IOException { + + init(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr); + if(callerUGI == null) { + String msg = "Unable to obtain user name, user not authenticated"; + throw new AuthorizationException(msg); + } + + String userName = callerUGI.getUserName(); + RMApp app = null; + try { + app = getRMAppForAppId(appId); + } + catch(NotFoundException e) { + RMAuditLogger.logFailure(userName, + AuditConstants.KILL_APP_REQUEST, "UNKNOWN", "RMWebService", + "Trying to kill/move an absent application " + appId); + throw e; + } + + if(!app.getState().toString().equals(appInfo.getState())) { + // user is attempting to change state. right we only + // allow users to kill the app + if(appInfo.getState().equals(YarnApplicationState.KILLED.toString())) { + return killApp(app, callerUGI, hsr); + } + throw new BadRequestException("Only '" + + YarnApplicationState.KILLED.toString() + + "' is allowed as a target state."); + } + + AppInfo ret = new AppInfo( + app, hasAccess(app, hsr), hsr.getScheme() + "://"); + return Response.status(Status.OK).entity(ret).build(); + } + + protected Response killApp(RMApp app, UserGroupInformation callerUGI, + HttpServletRequest hsr) throws IOException, InterruptedException { + + if(app == null) { + throw new IllegalArgumentException("app cannot be null"); + } + String userName = callerUGI.getUserName(); + if(app != null && + !hasAppAcess(app, callerUGI, ApplicationAccessType.MODIFY_APP)) { + String appId = app.getApplicationId().toString(); + String msg = "Unauthorized attempt to kill appid " + + appId + "by remote user " + userName; + RMAuditLogger.logFailure(userName, AuditConstants.KILL_APP_REQUEST, + "UNKNOWN", "RMWebService", + "Unauthorized attempt to kill appid " + appId); + return Response.status(Status.FORBIDDEN).entity(msg).build(); + } + + final ApplicationId appid = app.getApplicationId(); + KillApplicationResponse resp = callerUGI.doAs( + new PrivilegedExceptionAction() { + @Override + public KillApplicationResponse run() throws IOException, YarnException { + KillApplicationRequest req = + KillApplicationRequest.newInstance(appid); + return rm.getClientRMService().forceKillApplication(req); + } + }); + + AppInfo ret = new AppInfo( + app, hasAppAcess(app, callerUGI, ApplicationAccessType.MODIFY_APP), + hsr.getScheme() + "://"); + + if (resp.getIsKillCompleted()) { + RMAuditLogger.logSuccess(userName, AuditConstants.KILL_APP_REQUEST, + "RMWebService", app.getApplicationId()); + } else { + return Response.status(Status.ACCEPTED) + .entity(ret) + .header("Location", hsr.getRequestURL().toString()).build(); + } + + return Response.status(Status.OK).entity(ret).build(); + } + + private RMApp getRMAppForAppId(String appId) { + + if(appId == null || appId.isEmpty()) { + throw new NotFoundException("appId, " + appId + ", is empty or null"); + } + ApplicationId id; + try { + id = ConverterUtils.toApplicationId(recordFactory, appId); + } + catch(NumberFormatException e) { + throw new NotFoundException("appId is invalid"); + } + if(id == null) { + throw new NotFoundException("appId is invalid"); + } + RMApp app = rm.getRMContext().getRMApps().get(id); + if(app == null) { + throw new NotFoundException("app with id: " + appId + " not found"); + } + return app; + } + + private UserGroupInformation + getCallerUserGroupInformation(HttpServletRequest hsr) { + + String remoteUser = hsr.getRemoteUser(); + UserGroupInformation callerUGI = null; + if (remoteUser != null) { + callerUGI = UserGroupInformation.createRemoteUser(remoteUser); + } + + return callerUGI; + } + + protected Boolean hasAppAcess(RMApp app, + UserGroupInformation callerUGI, ApplicationAccessType type) { + if (callerUGI != null) { + if(!this.aclsManager.checkAccess(callerUGI, type, + app.getUser(), app.getApplicationId())) { + return false; + } + } + return true; + } + + protected Boolean hasQueueAcess(RMApp app, + UserGroupInformation callerUGI, QueueACL type) { + if (callerUGI != null) { + if(!this.queueACLsManager.checkAccess(callerUGI, type, + app.getQueue())) { + return false; + } + } + return true; + } + + //reuse the code in ClientRMService to create new app + @POST + @Path("/app/id") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public NewApplicationInfo createNewApplication( + @Context HttpServletRequest hsr) + throws AuthorizationException{ + + init(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr); + if(callerUGI == null) { + throw new AuthorizationException("Unable to obtain user " + + "name, user not authenticated"); + } + GetNewApplicationRequest req = recordFactory. + newRecordInstance(GetNewApplicationRequest.class); + GetNewApplicationResponse resp; + try { + resp = rm.getClientRMService().getNewApplication(req); + } + catch(YarnException e) { + String msg = "Unable to create new app from RM web service"; + LOG.error(msg, e); + throw new YarnRuntimeException(msg, e); + } + return new NewApplicationInfo(resp.getApplicationId(), + resp.getMaximumResourceCapability()); + } + + @POST + @Path("/app/{appid}") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Response submitNewApplication(AppSubmissionInfo newApp, + @Context HttpServletRequest hsr, + @PathParam("appid") String appId) + throws AuthorizationException, IOException, InterruptedException{ + + init(); + UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr); + if(callerUGI == null) { + throw new AuthorizationException("Unable to obtain user name, " + + "user not authenticated"); + } + + RMApp app = null; + try { + app = getRMAppForAppId(appId); + } + catch(NotFoundException e) { + // do nothing this is the expected response + ; + } + if(app != null) { + throw new BadRequestException("App with appId '" + + appId + "' already exists"); + } + + if(appId.equals(newApp.getApplicationId()) == false) { + throw new BadRequestException("appid in url and submitted " + + "info don't match"); + } + if(newApp.getApplicationName().isEmpty()) { + throw new BadRequestException("Application name missing"); + } + if(newApp.getResource().getMemory() == 0 || + newApp.getResource().getvCores() == 0) { + throw new BadRequestException("Requested resource memory " + + "and/or cores are 0"); + } + + ApplicationSubmissionContext appContext = createAppSubmissionContext(newApp); + final SubmitApplicationRequest req = + SubmitApplicationRequest.newInstance(appContext); + + callerUGI.doAs(new + PrivilegedExceptionAction() { + @Override + public SubmitApplicationResponse run() throws IOException, YarnException { + return rm.getClientRMService().submitApplication(req); + } + }); + + StringBuffer url = hsr.getRequestURL(); + return Response.status(Status.ACCEPTED) + .header("Location", url).build(); + } + + protected ApplicationSubmissionContext + createAppSubmissionContext(AppSubmissionInfo newApp) + throws BadRequestException { + + // create local resources and app submission context + + ApplicationId appid = ConverterUtils + .toApplicationId(recordFactory, newApp.getApplicationId()); + ApplicationSubmissionContext appContext = ApplicationSubmissionContext + .newInstance( + appid, + newApp.getApplicationName(), + newApp.getQueue(), + Priority.newInstance(newApp.getPriority()), + createContainerLaunchContext(newApp), + newApp.isUnmanagedAM(), + newApp.isCancelTokensWhenComplete(), + newApp.getMaxAppAttempts(), + createAppSubmissionContextResource(newApp), + newApp.getApplicationType()); + + appContext.setKeepContainersAcrossApplicationAttempts( + newApp.isKeepContainers()); + + return appContext; + } + + protected Resource + createAppSubmissionContextResource(AppSubmissionInfo newApp) + throws BadRequestException { + if(newApp.getResource().getvCores() > + rm.getConfig().getInt( + YarnConfiguration.RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES, + YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES)) { + String msg = "Requested more cores than configured max"; + throw new BadRequestException(msg); + } + if(newApp.getResource().getMemory() > + rm.getConfig().getInt( + YarnConfiguration.RM_SCHEDULER_MAXIMUM_ALLOCATION_MB, + YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB)) { + String msg = "Requested more memory than configured max"; + throw new BadRequestException(msg); + } + Resource r = Resource.newInstance( + newApp.getResource().getMemory(), + newApp.getResource().getvCores()); + return r; + } + + protected ContainerLaunchContext + createContainerLaunchContext(AppSubmissionInfo newApp) + throws BadRequestException { + + // create container launch context + + HashMap hmap = new HashMap(); + for(Map.Entry entry: + newApp.getContainerLaunchContext().getServiceData().entrySet()) { + if(entry.getValue().isEmpty() == false) { + hmap.put(entry.getKey(), ByteBuffer.wrap( + Base64.decode(entry.getValue()))); + } + } + + // verify local resource values + if(newApp.getContainerLaunchContext().getLocalResources().size() <= 0) { + throw new BadRequestException("Request must specify at " + + "least one local resource"); + } + HashMap hlr = new HashMap(); + for(Map.Entry entry: + newApp.getContainerLaunchContext().getLocalResources().entrySet()) { + LocalResourceInfo l = entry.getValue(); + if(l.getUrl() == null) { + throw new BadRequestException("File URI not set or was set " + + "to an incorrect " + + "value in the LocalResource for '" + entry.getKey() + "'"); + } + if(l.getType() == null) { + throw new BadRequestException("File type not set or was set" + + " to an incorrect " + + "value in the LocalResource for '" + entry.getKey() + "'"); + } + if(l.getVisibility() == null) { + throw new BadRequestException("File visibility not set or " + + "was set to an incorrect " + + "value in the LocalResource for '" + entry.getKey() + "'"); + } + LocalResource lr = LocalResource.newInstance( + ConverterUtils.getYarnUrlFromURI(l.getUrl()), + l.getType(), l.getVisibility(), l.getSize(), l.getTimestamp()); + hlr.put(entry.getKey(), lr); + } + + ContainerLaunchContext ctx = ContainerLaunchContext.newInstance( + hlr, + newApp.getContainerLaunchContext().getEnvironment(), + newApp.getContainerLaunchContext().getCommands(), + hmap, + null, + newApp.getContainerLaunchContext().getAcls()); + + if(newApp.getContainerLaunchContext().getTokens().isEmpty() == false) { + ctx.getTokens().put( + Base64.decode(newApp.getContainerLaunchContext().getTokens())); + } + return ctx; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppInfo.java index 6cb6114..849bdfd 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppInfo.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppInfo.java @@ -256,5 +256,113 @@ public int getAllocatedMB() { public int getAllocatedVCores() { return this.allocatedVCores; } + + public void setAppIdNum(String appIdNum) { + this.appIdNum = appIdNum; + } + + public void setTrackingUrlIsNotReady(boolean trackingUrlIsNotReady) { + this.trackingUrlIsNotReady = trackingUrlIsNotReady; + } + + public void setTrackingUrlPretty(String trackingUrlPretty) { + this.trackingUrlPretty = trackingUrlPretty; + } + + public void setAmContainerLogsExist(boolean amContainerLogsExist) { + this.amContainerLogsExist = amContainerLogsExist; + } + + public void setApplicationId(ApplicationId applicationId) { + this.applicationId = applicationId; + } + + public void setSchemePrefix(String schemePrefix) { + this.schemePrefix = schemePrefix; + } + + public void setId(String id) { + this.id = id; + } + + public void setUser(String user) { + this.user = user; + } + + public void setName(String name) { + this.name = name; + } + + public void setQueue(String queue) { + this.queue = queue; + } + + public void setState(YarnApplicationState state) { + this.state = state; + } + + public void setFinalStatus(FinalApplicationStatus finalStatus) { + this.finalStatus = finalStatus; + } + + public void setProgress(float progress) { + this.progress = progress; + } + + public void setTrackingUI(String trackingUI) { + this.trackingUI = trackingUI; + } + + public void setTrackingUrl(String trackingUrl) { + this.trackingUrl = trackingUrl; + } + + public void setDiagnostics(String diagnostics) { + this.diagnostics = diagnostics; + } + + public void setClusterId(long clusterId) { + this.clusterId = clusterId; + } + + public void setApplicationType(String applicationType) { + this.applicationType = applicationType; + } + + public void setApplicationTags(String applicationTags) { + this.applicationTags = applicationTags; + } + + public void setStartedTime(long startedTime) { + this.startedTime = startedTime; + } + + public void setFinishedTime(long finishedTime) { + this.finishedTime = finishedTime; + } + + public void setElapsedTime(long elapsedTime) { + this.elapsedTime = elapsedTime; + } + + public void setAmContainerLogs(String amContainerLogs) { + this.amContainerLogs = amContainerLogs; + } + + public void setAmHostHttpAddress(String amHostHttpAddress) { + this.amHostHttpAddress = amHostHttpAddress; + } + + public void setAllocatedMB(int allocatedMB) { + this.allocatedMB = allocatedMB; + } + + public void setAllocatedVCores(int allocatedVCores) { + this.allocatedVCores = allocatedVCores; + } + + public void setRunningContainers(int runningContainers) { + this.runningContainers = runningContainers; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppSubmissionInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppSubmissionInfo.java new file mode 100644 index 0000000..9bca076 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppSubmissionInfo.java @@ -0,0 +1,120 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.server.resourcemanager.webapp.dao; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.hadoop.yarn.api.records.Priority; + +@XmlRootElement(name="appsubmission") +@XmlAccessorType(XmlAccessType.FIELD) +public class AppSubmissionInfo { + + String applicationId; + String applicationName; + String queue; + int priority; + ContainerLaunchInfo containerInfo; + boolean isUnmanagedAM; + boolean cancelTokensWhenComplete; + int maxAppAttempts; + ResourceInfo resource; + String applicationType; + boolean keepContainers; + + public AppSubmissionInfo() { + applicationId = new String(); + applicationName = new String(); + containerInfo = new ContainerLaunchInfo(); + resource = new ResourceInfo(); + priority = Priority.UNDEFINED.getPriority(); + isUnmanagedAM = false; + } + + public String getApplicationId() { + return applicationId; + } + + public String getApplicationName() { + return applicationName; + } + public String getQueue() { + return queue; + } + public int getPriority() { + return priority; + } + public ContainerLaunchInfo getContainerLaunchContext() { + return containerInfo; + } + public boolean isUnmanagedAM() { + return isUnmanagedAM; + } + public boolean isCancelTokensWhenComplete() { + return cancelTokensWhenComplete; + } + public int getMaxAppAttempts() { + return maxAppAttempts; + } + public ResourceInfo getResource() { + return resource; + } + public String getApplicationType() { + return applicationType; + } + public boolean isKeepContainers() { + return keepContainers; + } + public void setApplicationId(String applicationId) { + this.applicationId = applicationId; + } + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + public void setQueue(String queue) { + this.queue = queue; + } + public void setPriority(int priority) { + this.priority = priority; + } + public void setContainerLaunchContext(ContainerLaunchInfo containerLaunchContext) { + this.containerInfo = containerLaunchContext; + } + public void setUnmanagedAM(boolean isUnmanagedAM) { + this.isUnmanagedAM = isUnmanagedAM; + } + public void setCancelTokensWhenComplete(boolean cancelTokensWhenComplete) { + this.cancelTokensWhenComplete = cancelTokensWhenComplete; + } + public void setMaxAppAttempts(int maxAppAttempts) { + this.maxAppAttempts = maxAppAttempts; + } + public void setResource(ResourceInfo resource) { + this.resource = resource; + } + public void setApplicationType(String applicationType) { + this.applicationType = applicationType; + } + public void setKeepContainers(boolean keepContainers) { + this.keepContainers = keepContainers; + } + +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ContainerLaunchInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ContainerLaunchInfo.java new file mode 100644 index 0000000..24a24d7 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ContainerLaunchInfo.java @@ -0,0 +1,94 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.server.resourcemanager.webapp.dao; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.hadoop.yarn.api.records.ApplicationAccessType; + +@XmlRootElement(name="containerinfo") +@XmlAccessorType(XmlAccessType.FIELD) +public class ContainerLaunchInfo { + Map localResources; + Map environment; + List commands; + Map serviceData; + String tokens; + Map acls; + + public ContainerLaunchInfo() { + localResources = new HashMap(); + environment = new HashMap(); + commands = new ArrayList(); + serviceData = new HashMap(); + tokens = new String(); + acls = new HashMap(); + } + + public Map getLocalResources() { + return localResources; + } + public Map getEnvironment() { + return environment; + } + public List getCommands() { + return commands; + } + + public Map getServiceData() { + return serviceData; + } + + public String getTokens() { + return tokens; + } + + public Map getAcls() { + return acls; + } + public void setLocalResources(Map localResources) { + this.localResources = localResources; + } + public void setEnvironment(Map environment) { + this.environment = environment; + } + public void setCommands(List commands) { + this.commands = commands; + } + + public void setServiceData(Map serviceData) { + this.serviceData = serviceData; + } + + public void setTokens(String tokens) { + this.tokens = tokens; + } + + public void setAcls(Map acls) { + this.acls = acls; + } + +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/LocalResourceInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/LocalResourceInfo.java new file mode 100644 index 0000000..b282000 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/LocalResourceInfo.java @@ -0,0 +1,87 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.server.resourcemanager.webapp.dao; + +import java.net.URI; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.hadoop.yarn.api.records.LocalResourceType; +import org.apache.hadoop.yarn.api.records.LocalResourceVisibility; + +@XmlRootElement(name="localresource") +@XmlAccessorType(XmlAccessType.FIELD) +public class LocalResourceInfo { + + URI url; + LocalResourceType type; + LocalResourceVisibility visibility; + long size; + long timestamp; + String pattern; + + public URI getUrl() { + return url; + } + public LocalResourceType getType() { + return type; + } + + public LocalResourceVisibility getVisibility() { + return visibility; + } + + public long getSize() { + return size; + } + + public long getTimestamp() { + return timestamp; + } + public String getPattern() { + return pattern; + } + public void setUrl(URI url) { + this.url = url; + } + public void setType(LocalResourceType type) { + this.type = type; + } + public void setVisibility(LocalResourceVisibility visibility) { + this.visibility = visibility; + } + public void setSize(long size) { + if(size <= 0) { + throw new IllegalArgumentException("size must be greater than 0"); + } + this.size = size; + } + public void setTimestamp(long timestamp) { + if(timestamp <= 0) { + throw new IllegalArgumentException("timestamp must be greater than 0"); + } + this.timestamp = timestamp; + } + public void setPattern(String pattern) { + this.pattern = pattern; + } + +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/NewApplicationInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/NewApplicationInfo.java new file mode 100644 index 0000000..f02b669 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/NewApplicationInfo.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.server.resourcemanager.webapp.dao; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.Resource; + +@XmlRootElement(name="newapp") +@XmlAccessorType(XmlAccessType.FIELD) +public class NewApplicationInfo { + + protected String id; + protected ResourceInfo resource; + + public NewApplicationInfo() { + return; + } + + public NewApplicationInfo(ApplicationId appId, Resource rs) { + id = appId.toString(); + resource = new ResourceInfo(rs); + } + + public String getId() { + return id; + } + + public ResourceInfo getResource() { + return resource; + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ResourceInfo.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ResourceInfo.java index 6b4422c..043351c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ResourceInfo.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ResourceInfo.java @@ -50,4 +50,12 @@ public int getvCores() { public String toString() { return ""; } + + public void setMemory(int memory) { + this.memory = memory; + } + + public void setvCores(int vCores) { + this.vCores = vCores; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMCustomAuthFilter.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMCustomAuthFilter.java new file mode 100644 index 0000000..d0a0404 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMCustomAuthFilter.java @@ -0,0 +1,57 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.yarn.server.resourcemanager.webapp; + +import java.util.Enumeration; +import java.util.Properties; + +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; + +import org.apache.hadoop.security.authentication.server.AuthenticationFilter; +import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler; + +import com.google.inject.Singleton; + +/* + * Helper class to allow testing of RM web services which require authorization + * Add this class as a filter in the Guice injector for the MockRM + * + */ + +@Singleton +public class TestRMCustomAuthFilter extends AuthenticationFilter { + + @Override + protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) throws ServletException { + Properties props = new Properties(); + Enumeration names = filterConfig.getInitParameterNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + if (name.startsWith(configPrefix)) { + String value = filterConfig.getInitParameter(name); + props.put(name.substring(configPrefix.length()), value); + } + } + props.put(AuthenticationFilter.AUTH_TYPE, "simple"); + props.put(PseudoAuthenticationHandler.ANONYMOUS_ALLOWED, "false"); + return props; + } + +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesApps.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesApps.java index 45b3803..3a82ca2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesApps.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesApps.java @@ -22,17 +22,27 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; import java.io.StringReader; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import javax.ws.rs.core.MediaType; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.yarn.api.records.ContainerState; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; +import org.apache.hadoop.yarn.api.records.LocalResourceType; +import org.apache.hadoop.yarn.api.records.LocalResourceVisibility; import org.apache.hadoop.yarn.api.records.YarnApplicationState; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.server.resourcemanager.MockAM; @@ -47,58 +57,54 @@ import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler; import org.apache.hadoop.yarn.server.resourcemanager.security.QueueACLsManager; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppSubmissionInfo; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.LocalResourceInfo; import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; +import org.apache.hadoop.yarn.util.ConverterUtils; import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; import org.apache.hadoop.yarn.webapp.WebServicesTestUtils; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; +import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; +import org.xml.sax.SAXException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; +import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse.Status; import com.sun.jersey.api.client.UniformInterfaceException; import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.WebResource.Builder; +import com.sun.jersey.api.json.JSONJAXBContext; +import com.sun.jersey.api.json.JSONMarshaller; import com.sun.jersey.core.util.MultivaluedMapImpl; import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import com.sun.jersey.test.framework.JerseyTest; import com.sun.jersey.test.framework.WebAppDescriptor; +@RunWith(Parameterized.class) public class TestRMWebServicesApps extends JerseyTest { private static MockRM rm; - + private static final int CONTAINER_MB = 1024; - private Injector injector = Guice.createInjector(new ServletModule() { - @Override - protected void configureServlets() { - bind(JAXBContextResolver.class); - bind(RMWebServices.class); - bind(GenericExceptionHandler.class); - Configuration conf = new Configuration(); - conf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, - YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS); - conf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class, - ResourceScheduler.class); - rm = new MockRM(conf); - bind(ResourceManager.class).toInstance(rm); - bind(RMContext.class).toInstance(rm.getRMContext()); - bind(ApplicationACLsManager.class).toInstance( - rm.getApplicationACLsManager()); - bind(QueueACLsManager.class).toInstance(rm.getQueueACLsManager()); - serve("/*").with(GuiceContainer.class); - } - }); + private Injector injector; + private String webserviceUserName = "testuser"; public class GuiceServletConfig extends GuiceServletContextListener { @@ -108,18 +114,82 @@ protected Injector getInjector() { } } + private Injector getNoAuthInjector() { + return Guice.createInjector(new ServletModule() { + @Override + protected void configureServlets() { + bind(JAXBContextResolver.class); + bind(RMWebServices.class); + bind(GenericExceptionHandler.class); + Configuration conf = new Configuration(); + conf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, + YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS); + conf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class, + ResourceScheduler.class); + rm = new MockRM(conf); + bind(ResourceManager.class).toInstance(rm); + bind(RMContext.class).toInstance(rm.getRMContext()); + bind(ApplicationACLsManager.class).toInstance( + rm.getApplicationACLsManager()); + bind(QueueACLsManager.class).toInstance(rm.getQueueACLsManager()); + serve("/*").with(GuiceContainer.class); + } + }); + } + + private Injector getSimpleAuthInjector() { + return Guice.createInjector(new ServletModule() { + @Override + protected void configureServlets() { + bind(JAXBContextResolver.class); + bind(RMWebServices.class); + bind(GenericExceptionHandler.class); + Configuration conf = new Configuration(); + conf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, + YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS); + conf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class, + ResourceScheduler.class); + conf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); + // set the admin acls otherwise all users are considered admins + // and we can't test authorization + conf.setStrings(YarnConfiguration.YARN_ADMIN_ACL, "testuser1"); + rm = new MockRM(conf); + bind(ResourceManager.class).toInstance(rm); + bind(RMContext.class).toInstance(rm.getRMContext()); + bind(ApplicationACLsManager.class).toInstance( + rm.getApplicationACLsManager()); + bind(QueueACLsManager.class).toInstance(rm.getQueueACLsManager()); + filter("/*").through(TestRMCustomAuthFilter.class); + serve("/*").with(GuiceContainer.class); + } + }); + } + + @Parameters + public static Collection guiceConfigs() { + return Arrays.asList(new Object[][] { { 0 }, { 1 } }); + } + @Before @Override public void setUp() throws Exception { super.setUp(); } - public TestRMWebServicesApps() { + public TestRMWebServicesApps(int run) { super(new WebAppDescriptor.Builder( - "org.apache.hadoop.yarn.server.resourcemanager.webapp") - .contextListenerClass(GuiceServletConfig.class) - .filterClass(com.google.inject.servlet.GuiceFilter.class) - .contextPath("jersey-guice-filter").servletPath("/").build()); + "org.apache.hadoop.yarn.server.resourcemanager.webapp") + .contextListenerClass(GuiceServletConfig.class) + .filterClass(com.google.inject.servlet.GuiceFilter.class) + .contextPath("jersey-guice-filter").servletPath("/").build()); + switch (run) { + case 0: + injector = getNoAuthInjector(); + break; + case 1: + injector = getSimpleAuthInjector(); + break; + } } @Test @@ -158,10 +228,11 @@ public void testAppsXML() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").accept(MediaType.APPLICATION_XML) - .get(ClientResponse.class); + + ClientResponse response = + this.constructWebResource("apps").accept(MediaType.APPLICATION_XML) + .get(ClientResponse.class); + assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); String xml = response.getEntity(String.class); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); @@ -185,11 +256,9 @@ public void testAppsXMLMulti() throws JSONException, Exception { rm.submitApp(2048, "testwordcount2", "user1"); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").accept(MediaType.APPLICATION_XML) - .get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps").accept(MediaType.APPLICATION_XML) + .get(ClientResponse.class); assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); String xml = response.getEntity(String.class); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); @@ -206,10 +275,9 @@ public void testAppsXMLMulti() throws JSONException, Exception { public void testAppsHelper(String path, RMApp app, String media) throws JSONException, Exception { - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path(path).accept(media).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource(path).accept(media).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -227,12 +295,11 @@ public void testAppsQueryState() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps") - .queryParam("state", YarnApplicationState.ACCEPTED.toString()) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("state", YarnApplicationState.ACCEPTED.toString()) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -254,12 +321,11 @@ public void testAppsQueryStates() throws JSONException, Exception { amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); MultivaluedMapImpl params = new MultivaluedMapImpl(); params.add("states", YarnApplicationState.ACCEPTED.toString()); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParams(params) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps").queryParams(params) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -268,15 +334,14 @@ public void testAppsQueryStates() throws JSONException, Exception { JSONArray array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 1, array.length()); assertEquals("state not equal to ACCEPTED", "ACCEPTED", array - .getJSONObject(0).getString("state")); + .getJSONObject(0).getString("state")); - r = resource(); params = new MultivaluedMapImpl(); params.add("states", YarnApplicationState.ACCEPTED.toString()); params.add("states", YarnApplicationState.KILLED.toString()); - response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParams(params) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + response = + this.constructWebResource("apps").queryParams(params) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -284,11 +349,11 @@ public void testAppsQueryStates() throws JSONException, Exception { assertEquals("incorrect number of elements", 1, apps.length()); array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 2, array.length()); - assertTrue("both app states of ACCEPTED and KILLED are not present", - (array.getJSONObject(0).getString("state").equals("ACCEPTED") && - array.getJSONObject(1).getString("state").equals("KILLED")) || - (array.getJSONObject(0).getString("state").equals("KILLED") && - array.getJSONObject(1).getString("state").equals("ACCEPTED"))); + assertTrue("both app states of ACCEPTED and KILLED are not present", (array + .getJSONObject(0).getString("state").equals("ACCEPTED") && array + .getJSONObject(1).getString("state").equals("KILLED")) + || (array.getJSONObject(0).getString("state").equals("KILLED") && array + .getJSONObject(1).getString("state").equals("ACCEPTED"))); rm.stop(); } @@ -303,12 +368,11 @@ public void testAppsQueryStatesComma() throws JSONException, Exception { amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); MultivaluedMapImpl params = new MultivaluedMapImpl(); params.add("states", YarnApplicationState.ACCEPTED.toString()); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParams(params) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps").queryParams(params) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -317,15 +381,14 @@ public void testAppsQueryStatesComma() throws JSONException, Exception { JSONArray array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 1, array.length()); assertEquals("state not equal to ACCEPTED", "ACCEPTED", array - .getJSONObject(0).getString("state")); + .getJSONObject(0).getString("state")); - r = resource(); params = new MultivaluedMapImpl(); params.add("states", YarnApplicationState.ACCEPTED.toString() + "," + YarnApplicationState.KILLED.toString()); - response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParams(params) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + response = + this.constructWebResource("apps").queryParams(params) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -333,12 +396,12 @@ public void testAppsQueryStatesComma() throws JSONException, Exception { assertEquals("incorrect number of elements", 1, apps.length()); array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 2, array.length()); - assertTrue("both app states of ACCEPTED and KILLED are not present", - (array.getJSONObject(0).getString("state").equals("ACCEPTED") && - array.getJSONObject(1).getString("state").equals("KILLED")) || - (array.getJSONObject(0).getString("state").equals("KILLED") && - array.getJSONObject(1).getString("state").equals("ACCEPTED"))); - + assertTrue("both app states of ACCEPTED and KILLED are not present", (array + .getJSONObject(0).getString("state").equals("ACCEPTED") && array + .getJSONObject(1).getString("state").equals("KILLED")) + || (array.getJSONObject(0).getString("state").equals("KILLED") && array + .getJSONObject(1).getString("state").equals("ACCEPTED"))); + rm.stop(); } @@ -348,12 +411,10 @@ public void testAppsQueryStatesNone() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps") - .queryParam("states", YarnApplicationState.RUNNING.toString()) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("states", YarnApplicationState.RUNNING.toString()) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -367,12 +428,12 @@ public void testAppsQueryStateNone() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps") - .queryParam("state", YarnApplicationState.RUNNING.toString()) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("state", YarnApplicationState.RUNNING.toString()) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -386,12 +447,10 @@ public void testAppsQueryStatesInvalid() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); try { - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("states", "INVALID_test") - .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); + this.constructWebResource("apps").queryParam("states", "INVALID_test") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); fail("should have thrown exception on invalid state query"); } catch (UniformInterfaceException ue) { ClientResponse response = ue.getResponse(); @@ -403,14 +462,12 @@ public void testAppsQueryStatesInvalid() throws JSONException, Exception { String message = exception.getString("message"); String type = exception.getString("exception"); String classname = exception.getString("javaClassName"); - WebServicesTestUtils.checkStringContains( - "exception message", - "Invalid application-state INVALID_test", - message); + WebServicesTestUtils.checkStringContains("exception message", + "Invalid application-state INVALID_test", message); WebServicesTestUtils.checkStringMatch("exception type", - "BadRequestException", type); + "BadRequestException", type); WebServicesTestUtils.checkStringMatch("exception classname", - "org.apache.hadoop.yarn.webapp.BadRequestException", classname); + "org.apache.hadoop.yarn.webapp.BadRequestException", classname); } finally { rm.stop(); @@ -423,12 +480,10 @@ public void testAppsQueryStateInvalid() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); try { - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("state", "INVALID_test") - .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); + this.constructWebResource("apps").queryParam("state", "INVALID_test") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); fail("should have thrown exception on invalid state query"); } catch (UniformInterfaceException ue) { ClientResponse response = ue.getResponse(); @@ -440,14 +495,12 @@ public void testAppsQueryStateInvalid() throws JSONException, Exception { String message = exception.getString("message"); String type = exception.getString("exception"); String classname = exception.getString("javaClassName"); - WebServicesTestUtils.checkStringContains( - "exception message", - "Invalid application-state INVALID_test", - message); + WebServicesTestUtils.checkStringContains("exception message", + "Invalid application-state INVALID_test", message); WebServicesTestUtils.checkStringMatch("exception type", - "BadRequestException", type); + "BadRequestException", type); WebServicesTestUtils.checkStringMatch("exception classname", - "org.apache.hadoop.yarn.webapp.BadRequestException", classname); + "org.apache.hadoop.yarn.webapp.BadRequestException", classname); } finally { rm.stop(); @@ -460,11 +513,12 @@ public void testAppsQueryFinalStatus() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("finalStatus", FinalApplicationStatus.UNDEFINED.toString()) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this + .constructWebResource("apps") + .queryParam("finalStatus", + FinalApplicationStatus.UNDEFINED.toString()) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -483,11 +537,10 @@ public void testAppsQueryFinalStatusNone() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("finalStatus", FinalApplicationStatus.KILLED.toString()) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("finalStatus", FinalApplicationStatus.KILLED.toString()) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -501,12 +554,11 @@ public void testAppsQueryFinalStatusInvalid() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); try { - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("finalStatus", "INVALID_test") - .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); + this.constructWebResource("apps") + .queryParam("finalStatus", "INVALID_test") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); fail("should have thrown exception on invalid state query"); } catch (UniformInterfaceException ue) { ClientResponse response = ue.getResponse(); @@ -519,14 +571,14 @@ public void testAppsQueryFinalStatusInvalid() throws JSONException, Exception { String type = exception.getString("exception"); String classname = exception.getString("javaClassName"); WebServicesTestUtils - .checkStringContains( - "exception message", - "org.apache.hadoop.yarn.api.records.FinalApplicationStatus.INVALID_test", - message); + .checkStringContains( + "exception message", + "org.apache.hadoop.yarn.api.records.FinalApplicationStatus.INVALID_test", + message); WebServicesTestUtils.checkStringMatch("exception type", - "IllegalArgumentException", type); + "IllegalArgumentException", type); WebServicesTestUtils.checkStringMatch("exception classname", - "java.lang.IllegalArgumentException", classname); + "java.lang.IllegalArgumentException", classname); } finally { rm.stop(); @@ -541,15 +593,13 @@ public void testAppsQueryUser() throws JSONException, Exception { rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - ClientResponse response = r - .path("ws") - .path("v1") - .path("cluster") - .path("apps") - .queryParam("user", + + ClientResponse response = + this + .constructWebResource("apps") + .queryParam("user", UserGroupInformation.getCurrentUser().getShortUserName()) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); @@ -569,11 +619,9 @@ public void testAppsQueryQueue() throws JSONException, Exception { rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("queue", "default") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps").queryParam("queue", "default") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -591,10 +639,9 @@ public void testAppsQueryLimit() throws JSONException, Exception { rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("limit", "2") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps").queryParam("limit", "2") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -614,10 +661,10 @@ public void testAppsQueryStartBegin() throws JSONException, Exception { rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("startedTimeBegin", String.valueOf(start)) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("startedTimeBegin", String.valueOf(start)) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -637,10 +684,10 @@ public void testAppsQueryStartBeginSome() throws JSONException, Exception { long start = System.currentTimeMillis(); Thread.sleep(1); rm.submitApp(CONTAINER_MB); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("startedTimeBegin", String.valueOf(start)) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("startedTimeBegin", String.valueOf(start)) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -660,10 +707,10 @@ public void testAppsQueryStartEnd() throws JSONException, Exception { rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("startedTimeEnd", String.valueOf(end)) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("startedTimeEnd", String.valueOf(end)) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -682,11 +729,11 @@ public void testAppsQueryStartBeginEnd() throws JSONException, Exception { long end = System.currentTimeMillis(); Thread.sleep(1); rm.submitApp(CONTAINER_MB); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("startedTimeBegin", String.valueOf(start)) - .queryParam("startedTimeEnd", String.valueOf(end)) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("startedTimeBegin", String.valueOf(start)) + .queryParam("startedTimeEnd", String.valueOf(end)) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -706,19 +753,18 @@ public void testAppsQueryFinishBegin() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); // finish App - MockAM am = rm - .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); + MockAM am = + rm.sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); am.registerAppAttempt(); am.unregisterAppAttempt(); amNodeManager.nodeHeartbeat(app1.getCurrentAppAttempt().getAppAttemptId(), - 1, ContainerState.COMPLETE); + 1, ContainerState.COMPLETE); rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); - - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("finishedTimeBegin", String.valueOf(start)) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("finishedTimeBegin", String.valueOf(start)) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -736,21 +782,21 @@ public void testAppsQueryFinishEnd() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); // finish App - MockAM am = rm - .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); + MockAM am = + rm.sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); am.registerAppAttempt(); am.unregisterAppAttempt(); amNodeManager.nodeHeartbeat(app1.getCurrentAppAttempt().getAppAttemptId(), - 1, ContainerState.COMPLETE); + 1, ContainerState.COMPLETE); rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); long end = System.currentTimeMillis(); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("finishedTimeEnd", String.valueOf(end)) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("finishedTimeEnd", String.valueOf(end)) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -770,22 +816,22 @@ public void testAppsQueryFinishBeginEnd() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); // finish App - MockAM am = rm - .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); + MockAM am = + rm.sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); am.registerAppAttempt(); am.unregisterAppAttempt(); amNodeManager.nodeHeartbeat(app1.getCurrentAppAttempt().getAppAttemptId(), - 1, ContainerState.COMPLETE); + 1, ContainerState.COMPLETE); rm.submitApp(CONTAINER_MB); rm.submitApp(CONTAINER_MB); long end = System.currentTimeMillis(); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("finishedTimeBegin", String.valueOf(start)) - .queryParam("finishedTimeEnd", String.valueOf(end)) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("finishedTimeBegin", String.valueOf(start)) + .queryParam("finishedTimeEnd", String.valueOf(end)) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -804,22 +850,22 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); // finish App - MockAM am = rm - .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); + MockAM am = + rm.sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); am.registerAppAttempt(); am.unregisterAppAttempt(); amNodeManager.nodeHeartbeat(app1.getCurrentAppAttempt().getAppAttemptId(), - 1, ContainerState.COMPLETE); + 1, ContainerState.COMPLETE); rm.submitApp(CONTAINER_MB, "", UserGroupInformation.getCurrentUser() - .getShortUserName(), null, false, null, 2, null, "MAPREDUCE"); + .getShortUserName(), null, false, null, 2, null, "MAPREDUCE"); rm.submitApp(CONTAINER_MB, "", UserGroupInformation.getCurrentUser() - .getShortUserName(), null, false, null, 2, null, "NON-YARN"); + .getShortUserName(), null, false, null, 2, null, "NON-YARN"); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("applicationTypes", "MAPREDUCE") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps") + .queryParam("applicationTypes", "MAPREDUCE") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -828,14 +874,13 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { JSONArray array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 1, array.length()); assertEquals("MAPREDUCE", - array.getJSONObject(0).getString("applicationType")); + array.getJSONObject(0).getString("applicationType")); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", "YARN") - .queryParam("applicationTypes", "MAPREDUCE") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", "YARN") + .queryParam("applicationTypes", "MAPREDUCE") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -844,17 +889,15 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 2, array.length()); assertTrue((array.getJSONObject(0).getString("applicationType") - .equals("YARN") && array.getJSONObject(1).getString("applicationType") - .equals("MAPREDUCE")) || - (array.getJSONObject(1).getString("applicationType").equals("YARN") - && array.getJSONObject(0).getString("applicationType") - .equals("MAPREDUCE"))); + .equals("YARN") && array.getJSONObject(1).getString("applicationType") + .equals("MAPREDUCE")) + || (array.getJSONObject(1).getString("applicationType").equals("YARN") && array + .getJSONObject(0).getString("applicationType").equals("MAPREDUCE"))); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", "YARN,NON-YARN") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", "YARN,NON-YARN") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -863,16 +906,14 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 2, array.length()); assertTrue((array.getJSONObject(0).getString("applicationType") - .equals("YARN") && array.getJSONObject(1).getString("applicationType") - .equals("NON-YARN")) || - (array.getJSONObject(1).getString("applicationType").equals("YARN") - && array.getJSONObject(0).getString("applicationType") - .equals("NON-YARN"))); - - r = resource(); - response = r.path("ws").path("v1").path("cluster") - .path("apps").queryParam("applicationTypes", "") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + .equals("YARN") && array.getJSONObject(1).getString("applicationType") + .equals("NON-YARN")) + || (array.getJSONObject(1).getString("applicationType").equals("YARN") && array + .getJSONObject(0).getString("applicationType").equals("NON-YARN"))); + + response = + this.constructWebResource("apps").queryParam("applicationTypes", "") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -881,12 +922,11 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 3, array.length()); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", "YARN,NON-YARN") - .queryParam("applicationTypes", "MAPREDUCE") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", "YARN,NON-YARN") + .queryParam("applicationTypes", "MAPREDUCE") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -895,12 +935,11 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 3, array.length()); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", "YARN") - .queryParam("applicationTypes", "") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", "YARN") + .queryParam("applicationTypes", "") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -908,14 +947,12 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { assertEquals("incorrect number of elements", 1, apps.length()); array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 1, array.length()); - assertEquals("YARN", - array.getJSONObject(0).getString("applicationType")); + assertEquals("YARN", array.getJSONObject(0).getString("applicationType")); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", ",,, ,, YARN ,, ,") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", ",,, ,, YARN ,, ,") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -923,14 +960,12 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { assertEquals("incorrect number of elements", 1, apps.length()); array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 1, array.length()); - assertEquals("YARN", - array.getJSONObject(0).getString("applicationType")); + assertEquals("YARN", array.getJSONObject(0).getString("applicationType")); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", ",,, ,, ,, ,") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", ",,, ,, ,, ,") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -939,11 +974,10 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 3, array.length()); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", "YARN, ,NON-YARN, ,,") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", "YARN, ,NON-YARN, ,,") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -952,18 +986,16 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 2, array.length()); assertTrue((array.getJSONObject(0).getString("applicationType") - .equals("YARN") && array.getJSONObject(1).getString("applicationType") - .equals("NON-YARN")) || - (array.getJSONObject(1).getString("applicationType").equals("YARN") - && array.getJSONObject(0).getString("applicationType") - .equals("NON-YARN"))); + .equals("YARN") && array.getJSONObject(1).getString("applicationType") + .equals("NON-YARN")) + || (array.getJSONObject(1).getString("applicationType").equals("YARN") && array + .getJSONObject(0).getString("applicationType").equals("NON-YARN"))); - r = resource(); response = - r.path("ws").path("v1").path("cluster").path("apps") - .queryParam("applicationTypes", " YARN, , ,,,") - .queryParam("applicationTypes", "MAPREDUCE , ,, ,") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + this.constructWebResource("apps") + .queryParam("applicationTypes", " YARN, , ,,,") + .queryParam("applicationTypes", "MAPREDUCE , ,, ,") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -972,11 +1004,10 @@ public void testAppsQueryAppTypes() throws JSONException, Exception { array = apps.getJSONArray("app"); assertEquals("incorrect number of elements", 2, array.length()); assertTrue((array.getJSONObject(0).getString("applicationType") - .equals("YARN") && array.getJSONObject(1).getString("applicationType") - .equals("MAPREDUCE")) || - (array.getJSONObject(1).getString("applicationType").equals("YARN") - && array.getJSONObject(0).getString("applicationType") - .equals("MAPREDUCE"))); + .equals("YARN") && array.getJSONObject(1).getString("applicationType") + .equals("MAPREDUCE")) + || (array.getJSONObject(1).getString("applicationType").equals("YARN") && array + .getJSONObject(0).getString("applicationType").equals("MAPREDUCE"))); rm.stop(); } @@ -987,27 +1018,28 @@ public void testAppStatistics() throws JSONException, Exception { rm.start(); MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 4096); Thread.sleep(1); - RMApp app1 = rm.submitApp(CONTAINER_MB, "", UserGroupInformation.getCurrentUser() - .getShortUserName(), null, false, null, 2, null, "MAPREDUCE"); + RMApp app1 = + rm.submitApp(CONTAINER_MB, "", UserGroupInformation.getCurrentUser() + .getShortUserName(), null, false, null, 2, null, "MAPREDUCE"); amNodeManager.nodeHeartbeat(true); // finish App - MockAM am = rm - .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); + MockAM am = + rm.sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId()); am.registerAppAttempt(); am.unregisterAppAttempt(); - amNodeManager.nodeHeartbeat(app1.getCurrentAppAttempt().getAppAttemptId(), - 1, ContainerState.COMPLETE); + amNodeManager.nodeHeartbeat( + app1.getCurrentAppAttempt().getAppAttemptId(), 1, + ContainerState.COMPLETE); rm.submitApp(CONTAINER_MB, "", UserGroupInformation.getCurrentUser() - .getShortUserName(), null, false, null, 2, null, "MAPREDUCE"); + .getShortUserName(), null, false, null, 2, null, "MAPREDUCE"); rm.submitApp(CONTAINER_MB, "", UserGroupInformation.getCurrentUser() - .getShortUserName(), null, false, null, 2, null, "OTHER"); + .getShortUserName(), null, false, null, 2, null, "OTHER"); // zero type, zero state - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("appstatistics") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("appstatistics") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -1015,13 +1047,13 @@ public void testAppStatistics() throws JSONException, Exception { assertEquals("incorrect number of elements", 1, appsStatInfo.length()); JSONArray statItems = appsStatInfo.getJSONArray("statItem"); assertEquals("incorrect number of elements", - YarnApplicationState.values().length, statItems.length()); + YarnApplicationState.values().length, statItems.length()); for (int i = 0; i < YarnApplicationState.values().length; ++i) { assertEquals("*", statItems.getJSONObject(0).getString("type")); if (statItems.getJSONObject(0).getString("state").equals("ACCEPTED")) { assertEquals("2", statItems.getJSONObject(0).getString("count")); - } else if ( - statItems.getJSONObject(0).getString("state").equals("FINISHED")) { + } else if (statItems.getJSONObject(0).getString("state") + .equals("FINISHED")) { assertEquals("1", statItems.getJSONObject(0).getString("count")); } else { assertEquals("0", statItems.getJSONObject(0).getString("count")); @@ -1029,11 +1061,10 @@ public void testAppStatistics() throws JSONException, Exception { } // zero type, one state - r = resource(); - response = r.path("ws").path("v1").path("cluster") - .path("appstatistics") - .queryParam("states", YarnApplicationState.ACCEPTED.toString()) - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + response = + this.constructWebResource("appstatistics") + .queryParam("states", YarnApplicationState.ACCEPTED.toString()) + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -1046,11 +1077,10 @@ public void testAppStatistics() throws JSONException, Exception { assertEquals("2", statItems.getJSONObject(0).getString("count")); // one type, zero state - r = resource(); - response = r.path("ws").path("v1").path("cluster") - .path("appstatistics") - .queryParam("applicationTypes", "MAPREDUCE") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + response = + this.constructWebResource("appstatistics") + .queryParam("applicationTypes", "MAPREDUCE") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -1058,13 +1088,13 @@ public void testAppStatistics() throws JSONException, Exception { assertEquals("incorrect number of elements", 1, appsStatInfo.length()); statItems = appsStatInfo.getJSONArray("statItem"); assertEquals("incorrect number of elements", - YarnApplicationState.values().length, statItems.length()); + YarnApplicationState.values().length, statItems.length()); for (int i = 0; i < YarnApplicationState.values().length; ++i) { assertEquals("mapreduce", statItems.getJSONObject(0).getString("type")); if (statItems.getJSONObject(0).getString("state").equals("ACCEPTED")) { assertEquals("1", statItems.getJSONObject(0).getString("count")); - } else if ( - statItems.getJSONObject(0).getString("state").equals("FINISHED")) { + } else if (statItems.getJSONObject(0).getString("state") + .equals("FINISHED")) { assertEquals("1", statItems.getJSONObject(0).getString("count")); } else { assertEquals("0", statItems.getJSONObject(0).getString("count")); @@ -1072,11 +1102,10 @@ public void testAppStatistics() throws JSONException, Exception { } // two types, zero state - r = resource(); - response = r.path("ws").path("v1").path("cluster") - .path("appstatistics") - .queryParam("applicationTypes", "MAPREDUCE,OTHER") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + response = + this.constructWebResource("appstatistics") + .queryParam("applicationTypes", "MAPREDUCE,OTHER") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); @@ -1087,20 +1116,22 @@ public void testAppStatistics() throws JSONException, Exception { String type = exception.getString("exception"); String className = exception.getString("javaClassName"); WebServicesTestUtils.checkStringContains("exception message", - "we temporarily support at most one applicationType", message); + "we temporarily support at most one applicationType", message); WebServicesTestUtils.checkStringEqual("exception type", - "BadRequestException", type); + "BadRequestException", type); WebServicesTestUtils.checkStringEqual("exception className", - "org.apache.hadoop.yarn.webapp.BadRequestException", className); + "org.apache.hadoop.yarn.webapp.BadRequestException", className); // one type, two states - r = resource(); - response = r.path("ws").path("v1").path("cluster") - .path("appstatistics") - .queryParam("states", YarnApplicationState.FINISHED.toString() - + "," + YarnApplicationState.ACCEPTED.toString()) - .queryParam("applicationTypes", "MAPREDUCE") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + response = + this + .constructWebResource("appstatistics") + .queryParam( + "states", + YarnApplicationState.FINISHED.toString() + "," + + YarnApplicationState.ACCEPTED.toString()) + .queryParam("applicationTypes", "MAPREDUCE") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -1110,20 +1141,20 @@ public void testAppStatistics() throws JSONException, Exception { assertEquals("incorrect number of elements", 2, statItems.length()); JSONObject statItem1 = statItems.getJSONObject(0); JSONObject statItem2 = statItems.getJSONObject(1); - assertTrue((statItem1.getString("state").equals("ACCEPTED") && - statItem2.getString("state").equals("FINISHED")) || - (statItem2.getString("state").equals("ACCEPTED") && - statItem1.getString("state").equals("FINISHED"))); + assertTrue((statItem1.getString("state").equals("ACCEPTED") && statItem2 + .getString("state").equals("FINISHED")) + || (statItem2.getString("state").equals("ACCEPTED") && statItem1 + .getString("state").equals("FINISHED"))); assertEquals("mapreduce", statItem1.getString("type")); assertEquals("1", statItem1.getString("count")); assertEquals("mapreduce", statItem2.getString("type")); assertEquals("1", statItem2.getString("count")); // invalid state - r = resource(); - response = r.path("ws").path("v1").path("cluster") - .path("appstatistics").queryParam("states", "wrong_state") - .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + response = + this.constructWebResource("appstatistics") + .queryParam("states", "wrong_state") + .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); json = response.getEntity(JSONObject.class); @@ -1134,11 +1165,11 @@ public void testAppStatistics() throws JSONException, Exception { type = exception.getString("exception"); className = exception.getString("javaClassName"); WebServicesTestUtils.checkStringContains("exception message", - "Invalid application-state wrong_state", message); + "Invalid application-state wrong_state", message); WebServicesTestUtils.checkStringEqual("exception type", - "BadRequestException", type); + "BadRequestException", type); WebServicesTestUtils.checkStringEqual("exception className", - "org.apache.hadoop.yarn.webapp.BadRequestException", className); + "org.apache.hadoop.yarn.webapp.BadRequestException", className); } finally { rm.stop(); } @@ -1151,7 +1182,7 @@ public void testSingleApp() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); amNodeManager.nodeHeartbeat(true); testSingleAppsHelper(app1.getApplicationId().toString(), app1, - MediaType.APPLICATION_JSON); + MediaType.APPLICATION_JSON); rm.stop(); } @@ -1162,7 +1193,7 @@ public void testSingleAppsSlash() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); testSingleAppsHelper(app1.getApplicationId().toString() + "/", app1, - MediaType.APPLICATION_JSON); + MediaType.APPLICATION_JSON); rm.stop(); } @@ -1182,12 +1213,10 @@ public void testInvalidApp() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); try { - r.path("ws").path("v1").path("cluster").path("apps") - .path("application_invalid_12").accept(MediaType.APPLICATION_JSON) - .get(JSONObject.class); + this.constructWebResource("apps", "application_invalid_12") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); fail("should have thrown exception on invalid appid"); } catch (UniformInterfaceException ue) { ClientResponse response = ue.getResponse(); @@ -1201,11 +1230,11 @@ public void testInvalidApp() throws JSONException, Exception { String type = exception.getString("exception"); String classname = exception.getString("javaClassName"); WebServicesTestUtils.checkStringMatch("exception message", - "For input string: \"invalid\"", message); + "For input string: \"invalid\"", message); WebServicesTestUtils.checkStringMatch("exception type", - "NumberFormatException", type); + "NumberFormatException", type); WebServicesTestUtils.checkStringMatch("exception classname", - "java.lang.NumberFormatException", classname); + "java.lang.NumberFormatException", classname); } finally { rm.stop(); @@ -1218,12 +1247,10 @@ public void testNonexistApp() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); try { - r.path("ws").path("v1").path("cluster").path("apps") - .path("application_00000_0099").accept(MediaType.APPLICATION_JSON) - .get(JSONObject.class); + this.constructWebResource("apps", "application_00000_0099") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); fail("should have thrown exception on invalid appid"); } catch (UniformInterfaceException ue) { ClientResponse response = ue.getResponse(); @@ -1238,12 +1265,12 @@ public void testNonexistApp() throws JSONException, Exception { String type = exception.getString("exception"); String classname = exception.getString("javaClassName"); WebServicesTestUtils.checkStringMatch("exception message", - "java.lang.Exception: app with id: application_00000_0099 not found", - message); + "java.lang.Exception: app with id: application_00000_0099 not found", + message); WebServicesTestUtils.checkStringMatch("exception type", - "NotFoundException", type); + "NotFoundException", type); WebServicesTestUtils.checkStringMatch("exception classname", - "org.apache.hadoop.yarn.webapp.NotFoundException", classname); + "org.apache.hadoop.yarn.webapp.NotFoundException", classname); } finally { rm.stop(); } @@ -1251,9 +1278,9 @@ public void testNonexistApp() throws JSONException, Exception { public void testSingleAppsHelper(String path, RMApp app, String media) throws JSONException, Exception { - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").path(path).accept(media).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps", path).accept(media) + .get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); @@ -1267,10 +1294,9 @@ public void testSingleAppsXML() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").path(app1.getApplicationId().toString()) - .accept(MediaType.APPLICATION_XML).get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps", app1.getApplicationId().toString()) + .accept(MediaType.APPLICATION_XML).get(ClientResponse.class); assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); String xml = response.getEntity(String.class); @@ -1288,29 +1314,29 @@ public void testSingleAppsXML() throws JSONException, Exception { public void verifyAppsXML(NodeList nodes, RMApp app) throws JSONException, Exception { - for (int i = 0; i < nodes.getLength(); i++) { + for (int i = 0; i < nodes.getLength(); i++) { Element element = (Element) nodes.item(i); verifyAppInfoGeneric(app, - WebServicesTestUtils.getXmlString(element, "id"), - WebServicesTestUtils.getXmlString(element, "user"), - WebServicesTestUtils.getXmlString(element, "name"), - WebServicesTestUtils.getXmlString(element, "applicationType"), - WebServicesTestUtils.getXmlString(element, "queue"), - WebServicesTestUtils.getXmlString(element, "state"), - WebServicesTestUtils.getXmlString(element, "finalStatus"), - WebServicesTestUtils.getXmlFloat(element, "progress"), - WebServicesTestUtils.getXmlString(element, "trackingUI"), - WebServicesTestUtils.getXmlString(element, "diagnostics"), - WebServicesTestUtils.getXmlLong(element, "clusterId"), - WebServicesTestUtils.getXmlLong(element, "startedTime"), - WebServicesTestUtils.getXmlLong(element, "finishedTime"), - WebServicesTestUtils.getXmlLong(element, "elapsedTime"), - WebServicesTestUtils.getXmlString(element, "amHostHttpAddress"), - WebServicesTestUtils.getXmlString(element, "amContainerLogs"), - WebServicesTestUtils.getXmlInt(element, "allocatedMB"), - WebServicesTestUtils.getXmlInt(element, "allocatedVCores"), - WebServicesTestUtils.getXmlInt(element, "runningContainers")); + WebServicesTestUtils.getXmlString(element, "id"), + WebServicesTestUtils.getXmlString(element, "user"), + WebServicesTestUtils.getXmlString(element, "name"), + WebServicesTestUtils.getXmlString(element, "applicationType"), + WebServicesTestUtils.getXmlString(element, "queue"), + WebServicesTestUtils.getXmlString(element, "state"), + WebServicesTestUtils.getXmlString(element, "finalStatus"), + WebServicesTestUtils.getXmlFloat(element, "progress"), + WebServicesTestUtils.getXmlString(element, "trackingUI"), + WebServicesTestUtils.getXmlString(element, "diagnostics"), + WebServicesTestUtils.getXmlLong(element, "clusterId"), + WebServicesTestUtils.getXmlLong(element, "startedTime"), + WebServicesTestUtils.getXmlLong(element, "finishedTime"), + WebServicesTestUtils.getXmlLong(element, "elapsedTime"), + WebServicesTestUtils.getXmlString(element, "amHostHttpAddress"), + WebServicesTestUtils.getXmlString(element, "amContainerLogs"), + WebServicesTestUtils.getXmlInt(element, "allocatedMB"), + WebServicesTestUtils.getXmlInt(element, "allocatedVCores"), + WebServicesTestUtils.getXmlInt(element, "runningContainers")); } } @@ -1321,53 +1347,54 @@ public void verifyAppInfo(JSONObject info, RMApp app) throws JSONException, assertEquals("incorrect number of elements", 20, info.length()); verifyAppInfoGeneric(app, info.getString("id"), info.getString("user"), - info.getString("name"), info.getString("applicationType"), info.getString("queue"), - info.getString("state"), info.getString("finalStatus"), - (float) info.getDouble("progress"), info.getString("trackingUI"), - info.getString("diagnostics"), info.getLong("clusterId"), - info.getLong("startedTime"), info.getLong("finishedTime"), - info.getLong("elapsedTime"), info.getString("amHostHttpAddress"), - info.getString("amContainerLogs"), info.getInt("allocatedMB"), - info.getInt("allocatedVCores"), info.getInt("runningContainers")); + info.getString("name"), info.getString("applicationType"), + info.getString("queue"), info.getString("state"), + info.getString("finalStatus"), (float) info.getDouble("progress"), + info.getString("trackingUI"), info.getString("diagnostics"), + info.getLong("clusterId"), info.getLong("startedTime"), + info.getLong("finishedTime"), info.getLong("elapsedTime"), + info.getString("amHostHttpAddress"), info.getString("amContainerLogs"), + info.getInt("allocatedMB"), info.getInt("allocatedVCores"), + info.getInt("runningContainers")); } public void verifyAppInfoGeneric(RMApp app, String id, String user, - String name, String applicationType, String queue, String state, String finalStatus, - float progress, String trackingUI, String diagnostics, long clusterId, - long startedTime, long finishedTime, long elapsedTime, - String amHostHttpAddress, String amContainerLogs, int allocatedMB, - int allocatedVCores, int numContainers) throws JSONException, - Exception { + String name, String applicationType, String queue, String state, + String finalStatus, float progress, String trackingUI, + String diagnostics, long clusterId, long startedTime, long finishedTime, + long elapsedTime, String amHostHttpAddress, String amContainerLogs, + int allocatedMB, int allocatedVCores, int numContainers) + throws JSONException, Exception { WebServicesTestUtils.checkStringMatch("id", app.getApplicationId() - .toString(), id); + .toString(), id); WebServicesTestUtils.checkStringMatch("user", app.getUser(), user); WebServicesTestUtils.checkStringMatch("name", app.getName(), name); WebServicesTestUtils.checkStringMatch("applicationType", app.getApplicationType(), applicationType); WebServicesTestUtils.checkStringMatch("queue", app.getQueue(), queue); WebServicesTestUtils.checkStringMatch("state", app.getState().toString(), - state); + state); WebServicesTestUtils.checkStringMatch("finalStatus", app - .getFinalApplicationStatus().toString(), finalStatus); + .getFinalApplicationStatus().toString(), finalStatus); assertEquals("progress doesn't match", 0, progress, 0.0); WebServicesTestUtils.checkStringMatch("trackingUI", "UNASSIGNED", - trackingUI); + trackingUI); WebServicesTestUtils.checkStringMatch("diagnostics", app.getDiagnostics() - .toString(), diagnostics); + .toString(), diagnostics); assertEquals("clusterId doesn't match", - ResourceManager.getClusterTimeStamp(), clusterId); + ResourceManager.getClusterTimeStamp(), clusterId); assertEquals("startedTime doesn't match", app.getStartTime(), startedTime); assertEquals("finishedTime doesn't match", app.getFinishTime(), - finishedTime); + finishedTime); assertTrue("elapsed time not greater than 0", elapsedTime > 0); WebServicesTestUtils.checkStringMatch("amHostHttpAddress", app - .getCurrentAppAttempt().getMasterContainer().getNodeHttpAddress(), - amHostHttpAddress); + .getCurrentAppAttempt().getMasterContainer().getNodeHttpAddress(), + amHostHttpAddress); assertTrue("amContainerLogs doesn't match", - amContainerLogs.startsWith("http://")); + amContainerLogs.startsWith("http://")); assertTrue("amContainerLogs doesn't contain user info", - amContainerLogs.endsWith("/" + app.getUser())); + amContainerLogs.endsWith("/" + app.getUser())); assertEquals("allocatedMB doesn't match", 1024, allocatedMB); assertEquals("allocatedVCores doesn't match", 1, allocatedVCores); assertEquals("numContainers doesn't match", 1, numContainers); @@ -1380,24 +1407,25 @@ public void testAppAttempts() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); amNodeManager.nodeHeartbeat(true); testAppAttemptsHelper(app1.getApplicationId().toString(), app1, - MediaType.APPLICATION_JSON); + MediaType.APPLICATION_JSON); rm.stop(); } - @Test (timeout = 20000) + @Test(timeout = 20000) public void testMultipleAppAttempts() throws JSONException, Exception { rm.start(); MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 8192); RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); MockAM am = MockRM.launchAndRegisterAM(app1, rm, amNodeManager); - int maxAppAttempts = rm.getConfig().getInt( - YarnConfiguration.RM_AM_MAX_ATTEMPTS, - YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS); + int maxAppAttempts = + rm.getConfig().getInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, + YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS); assertTrue(maxAppAttempts > 1); int numAttempt = 1; while (true) { // fail the AM by sending CONTAINER_FINISHED event without registering. - amNodeManager.nodeHeartbeat(am.getApplicationAttemptId(), 1, ContainerState.COMPLETE); + amNodeManager.nodeHeartbeat(am.getApplicationAttemptId(), 1, + ContainerState.COMPLETE); am.waitForState(RMAppAttemptState.FAILED); if (numAttempt == maxAppAttempts) { rm.waitForState(app1.getApplicationId(), RMAppState.FAILED); @@ -1408,10 +1436,10 @@ public void testMultipleAppAttempts() throws JSONException, Exception { am = MockRM.launchAndRegisterAM(app1, rm, amNodeManager); numAttempt++; } - assertEquals("incorrect number of attempts", maxAppAttempts, - app1.getAppAttempts().values().size()); + assertEquals("incorrect number of attempts", maxAppAttempts, app1 + .getAppAttempts().values().size()); testAppAttemptsHelper(app1.getApplicationId().toString(), app1, - MediaType.APPLICATION_JSON); + MediaType.APPLICATION_JSON); rm.stop(); } @@ -1422,7 +1450,7 @@ public void testAppAttemptsSlash() throws JSONException, Exception { RMApp app1 = rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); testAppAttemptsHelper(app1.getApplicationId().toString() + "/", app1, - MediaType.APPLICATION_JSON); + MediaType.APPLICATION_JSON); rm.stop(); } @@ -1442,12 +1470,10 @@ public void testInvalidAppAttempts() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); try { - r.path("ws").path("v1").path("cluster").path("apps") - .path("application_invalid_12").accept(MediaType.APPLICATION_JSON) - .get(JSONObject.class); + this.constructWebResource("apps", "application_invalid_12") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); fail("should have thrown exception on invalid appid"); } catch (UniformInterfaceException ue) { ClientResponse response = ue.getResponse(); @@ -1461,11 +1487,11 @@ public void testInvalidAppAttempts() throws JSONException, Exception { String type = exception.getString("exception"); String classname = exception.getString("javaClassName"); WebServicesTestUtils.checkStringMatch("exception message", - "For input string: \"invalid\"", message); + "For input string: \"invalid\"", message); WebServicesTestUtils.checkStringMatch("exception type", - "NumberFormatException", type); + "NumberFormatException", type); WebServicesTestUtils.checkStringMatch("exception classname", - "java.lang.NumberFormatException", classname); + "java.lang.NumberFormatException", classname); } finally { rm.stop(); @@ -1478,12 +1504,10 @@ public void testNonexistAppAttempts() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); try { - r.path("ws").path("v1").path("cluster").path("apps") - .path("application_00000_0099").accept(MediaType.APPLICATION_JSON) - .get(JSONObject.class); + this.constructWebResource("apps", "application_00000_0099") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); fail("should have thrown exception on invalid appid"); } catch (UniformInterfaceException ue) { ClientResponse response = ue.getResponse(); @@ -1498,12 +1522,12 @@ public void testNonexistAppAttempts() throws JSONException, Exception { String type = exception.getString("exception"); String classname = exception.getString("javaClassName"); WebServicesTestUtils.checkStringMatch("exception message", - "java.lang.Exception: app with id: application_00000_0099 not found", - message); + "java.lang.Exception: app with id: application_00000_0099 not found", + message); WebServicesTestUtils.checkStringMatch("exception type", - "NotFoundException", type); + "NotFoundException", type); WebServicesTestUtils.checkStringMatch("exception classname", - "org.apache.hadoop.yarn.webapp.NotFoundException", classname); + "org.apache.hadoop.yarn.webapp.NotFoundException", classname); } finally { rm.stop(); } @@ -1511,10 +1535,9 @@ public void testNonexistAppAttempts() throws JSONException, Exception { public void testAppAttemptsHelper(String path, RMApp app, String media) throws JSONException, Exception { - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").path(path).path("appattempts").accept(media) - .get(ClientResponse.class); + ClientResponse response = + this.constructWebResource("apps", path, "appattempts").accept(media) + .get(ClientResponse.class); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); @@ -1524,7 +1547,7 @@ public void testAppAttemptsHelper(String path, RMApp app, String media) Collection attempts = app.getAppAttempts().values(); assertEquals("incorrect number of elements", attempts.size(), - jsonArray.length()); + jsonArray.length()); // Verify these parallel arrays are the same int i = 0; @@ -1541,11 +1564,11 @@ public void testAppAttemptsXML() throws JSONException, Exception { MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", user); amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - ClientResponse response = r.path("ws").path("v1").path("cluster") - .path("apps").path(app1.getApplicationId().toString()) - .path("appattempts").accept(MediaType.APPLICATION_XML) - .get(ClientResponse.class); + ClientResponse response = + this + .constructWebResource("apps", app1.getApplicationId().toString(), + "appattempts").accept(MediaType.APPLICATION_XML) + .get(ClientResponse.class); assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); String xml = response.getEntity(String.class); @@ -1563,54 +1586,530 @@ public void testAppAttemptsXML() throws JSONException, Exception { } public void verifyAppAttemptsXML(NodeList nodes, RMAppAttempt appAttempt, - String user) - throws JSONException, Exception { + String user) throws JSONException, Exception { for (int i = 0; i < nodes.getLength(); i++) { Element element = (Element) nodes.item(i); verifyAppAttemptInfoGeneric(appAttempt, - WebServicesTestUtils.getXmlInt(element, "id"), - WebServicesTestUtils.getXmlLong(element, "startTime"), - WebServicesTestUtils.getXmlString(element, "containerId"), - WebServicesTestUtils.getXmlString(element, "nodeHttpAddress"), - WebServicesTestUtils.getXmlString(element, "nodeId"), - WebServicesTestUtils.getXmlString(element, "logsLink"), user); + WebServicesTestUtils.getXmlInt(element, "id"), + WebServicesTestUtils.getXmlLong(element, "startTime"), + WebServicesTestUtils.getXmlString(element, "containerId"), + WebServicesTestUtils.getXmlString(element, "nodeHttpAddress"), + WebServicesTestUtils.getXmlString(element, "nodeId"), + WebServicesTestUtils.getXmlString(element, "logsLink"), user); } } public void verifyAppAttemptsInfo(JSONObject info, RMAppAttempt appAttempt, - String user) - throws JSONException, Exception { + String user) throws JSONException, Exception { assertEquals("incorrect number of elements", 6, info.length()); verifyAppAttemptInfoGeneric(appAttempt, info.getInt("id"), - info.getLong("startTime"), info.getString("containerId"), - info.getString("nodeHttpAddress"), info.getString("nodeId"), - info.getString("logsLink"), user); + info.getLong("startTime"), info.getString("containerId"), + info.getString("nodeHttpAddress"), info.getString("nodeId"), + info.getString("logsLink"), user); } public void verifyAppAttemptInfoGeneric(RMAppAttempt appAttempt, int id, - long startTime, String containerId, String nodeHttpAddress, String nodeId, - String logsLink, String user) - throws JSONException, Exception { + long startTime, String containerId, String nodeHttpAddress, + String nodeId, String logsLink, String user) throws JSONException, + Exception { assertEquals("id doesn't match", appAttempt.getAppAttemptId() - .getAttemptId(), id); + .getAttemptId(), id); assertEquals("startedTime doesn't match", appAttempt.getStartTime(), - startTime); + startTime); WebServicesTestUtils.checkStringMatch("containerId", appAttempt - .getMasterContainer().getId().toString(), containerId); + .getMasterContainer().getId().toString(), containerId); WebServicesTestUtils.checkStringMatch("nodeHttpAddress", appAttempt - .getMasterContainer().getNodeHttpAddress(), nodeHttpAddress); + .getMasterContainer().getNodeHttpAddress(), nodeHttpAddress); WebServicesTestUtils.checkStringMatch("nodeId", appAttempt - .getMasterContainer().getNodeId().toString(), nodeId); + .getMasterContainer().getNodeId().toString(), nodeId); assertTrue("logsLink doesn't match", logsLink.startsWith("//")); - assertTrue( - "logsLink doesn't contain user info", logsLink.endsWith("/" - + user)); + assertTrue("logsLink doesn't contain user info", + logsLink.endsWith("/" + user)); + } + + private WebResource constructWebResource(WebResource r, String... paths) { + WebResource rt = r; + for (String path : paths) { + rt = rt.path(path); + } + if (rm.getConfig().getBoolean(YarnConfiguration.YARN_ACL_ENABLE, false) == true) { + rt = rt.queryParam("user.name", webserviceUserName); + } + return rt; } -} + private WebResource constructWebResource(String... paths) { + WebResource r = resource(); + WebResource ws = r.path("ws").path("v1").path("cluster"); + return this.constructWebResource(ws, paths); + } + + @Test(timeout = 90000) + public void testSingleAppKill() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + + String[] mediaTypes = + { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }; + MediaType[] contentTypes = + { MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_XML_TYPE }; + for (String mediaType : mediaTypes) { + for(MediaType contentType: contentTypes) { + RMApp app = rm.submitApp(CONTAINER_MB, "", webserviceUserName); + amNodeManager.nodeHeartbeat(true); + ClientResponse response = this + .constructWebResource("apps", app.getApplicationId().toString()) + .accept(mediaType).get(ClientResponse.class); + AppInfo info = response.getEntity(AppInfo.class); + info.setState(YarnApplicationState.KILLED); + + Object entity; + if(contentType == MediaType.APPLICATION_JSON_TYPE) { + entity = appInfoToJSON(info); + } + else { + entity = info; + } + response = this + .constructWebResource("apps", app.getApplicationId().toString()) + .entity(entity, contentType) + .accept(mediaType) + .put(ClientResponse.class); + + + if (rm.getConfig() + .getBoolean(YarnConfiguration.YARN_ACL_ENABLE, false) == false) { + assertEquals(Status.UNAUTHORIZED, + response.getClientResponseStatus()); + continue; + } + assertEquals(Status.ACCEPTED, response.getClientResponseStatus()); + if (mediaType == MediaType.APPLICATION_JSON) { + verifyAppKillJson(response, RMAppState.ACCEPTED); + } else { + verifyAppKillXML(response, RMAppState.ACCEPTED); + } + + String locationHeaderValue = + response.getHeaders().getFirst("Location"); + Client c = Client.create(); + WebResource tmp = c.resource(locationHeaderValue); + if (rm.getConfig() + .getBoolean(YarnConfiguration.YARN_ACL_ENABLE, false) == true) { + tmp = tmp.queryParam("user.name", webserviceUserName); + } + response = tmp.get(ClientResponse.class); + assertEquals(Status.OK, response.getClientResponseStatus()); + assertTrue(locationHeaderValue.endsWith("/ws/v1/cluster/apps/" + + app.getApplicationId().toString())); + + while (true) { + Thread.sleep(1000); + response = this + .constructWebResource("apps", app.getApplicationId().toString()) + .accept(mediaType).entity(entity, contentType) + .put(ClientResponse.class); + assertTrue((response.getClientResponseStatus() == Status.ACCEPTED) + || (response.getClientResponseStatus() == Status.OK)); + if (response.getClientResponseStatus() == Status.OK) { + if (mediaType == MediaType.APPLICATION_JSON) { + verifyAppKillJson(response, RMAppState.KILLED); + } else { + verifyAppKillXML(response, RMAppState.KILLED); + } + break; + } + } + } + } + + rm.stop(); + return; + } + + private static String appInfoToJSON(AppInfo info) throws Exception { + StringWriter sw = new StringWriter(); + JSONJAXBContext ctx = new JSONJAXBContext(AppInfo.class); + JSONMarshaller jm = ctx.createJSONMarshaller(); + jm.marshallToJSON(info, sw); + String json = "{\"app\":"; + json = json.concat(sw.toString()); + json = json.concat("}"); + return json; + } + + protected static void verifyAppKillJson(ClientResponse response, + RMAppState state) throws JSONException { + + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject appObj = json.getJSONObject("app"); + assertEquals("app state incorrect", state.toString(), + appObj.getString("state")); + return; + } + + protected static void verifyAppKillXML(ClientResponse response, + RMAppState appState) throws ParserConfigurationException, IOException, + SAXException { + assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); + String xml = response.getEntity(String.class); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + InputSource is = new InputSource(); + is.setCharacterStream(new StringReader(xml)); + Document dom = db.parse(is); + NodeList nodes = dom.getElementsByTagName("app"); + assertEquals("incorrect number of elements", 1, nodes.getLength()); + Element element = (Element) nodes.item(0); + String state = WebServicesTestUtils.getXmlString(element, "state"); + assertEquals("app state incorrect", appState.toString(), state); + return; + } + + @Test(timeout = 30000) + public void testSingleAppKillUnauthorized() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + + String[] mediaTypes = + { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }; + for (String mediaType : mediaTypes) { + RMApp app = rm.submitApp(CONTAINER_MB, "test", "someuser"); + amNodeManager.nodeHeartbeat(true); + ClientResponse response = this + .constructWebResource("apps", app.getApplicationId().toString()) + .accept(mediaType).get(ClientResponse.class); + AppInfo info = response.getEntity(AppInfo.class); + info.setState(YarnApplicationState.KILLED); + + response = this + .constructWebResource("apps", app.getApplicationId().toString()) + .accept(mediaType).entity(info, MediaType.APPLICATION_XML) + .put(ClientResponse.class); + if (rm.getConfig() + .getBoolean(YarnConfiguration.YARN_ACL_ENABLE, false) == false) { + assertEquals(Status.UNAUTHORIZED, response.getClientResponseStatus()); + } else { + assertEquals(Status.FORBIDDEN, response.getClientResponseStatus()); + } + } + + // there's a condition where if the rm is stopped while an app + // is being killed, it can lead to the test timing out, hence the sleep + Thread.sleep(3000); + + rm.stop(); + return; + + } + @Test + public void testSingleAppKillInvalidId() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + amNodeManager.nodeHeartbeat(true); + String[] testAppIds = { "application_1391705042196_0001", + "random_string" }; + for (String testAppId : testAppIds) { + AppInfo info = new AppInfo(); + ClientResponse response = this.constructWebResource("apps", testAppId) + .accept(MediaType.APPLICATION_XML) + .entity(info, MediaType.APPLICATION_XML) + .put(ClientResponse.class); + if (rm.getConfig() + .getBoolean(YarnConfiguration.YARN_ACL_ENABLE, false) == false) { + assertEquals(Status.UNAUTHORIZED, response.getClientResponseStatus()); + continue; + } + assertEquals(Status.NOT_FOUND, response.getClientResponseStatus()); + } + rm.stop(); + return; + } + + @After + @Override + public void tearDown() throws Exception { + if (rm != null) { + rm.stop(); + } + super.tearDown(); + } + + @Test + public void testGetNewApplicationIdAndSubmit() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + amNodeManager.nodeHeartbeat(true); + String mediaTypes[] = + { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }; + String id = ""; + for (int i = 0; i < 2; ++i) { + for (String acceptMedia : mediaTypes) { + for (String contentMedia : mediaTypes) { + ClientResponse response = + this.constructWebResource("app", "id").accept(acceptMedia) + .post(ClientResponse.class); + if (rm.getConfig() + .getBoolean(YarnConfiguration.YARN_ACL_ENABLE, false) == false) { + assertEquals(Status.UNAUTHORIZED, + response.getClientResponseStatus()); + } else { + if (acceptMedia.equals(MediaType.APPLICATION_XML)) { + assertEquals(Status.OK, response.getClientResponseStatus()); + assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); + String xml = response.getEntity(String.class); + DocumentBuilderFactory dbf = + DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + InputSource is = new InputSource(); + is.setCharacterStream(new StringReader(xml)); + Document dom = db.parse(is); + NodeList nodes = dom.getElementsByTagName("newapp"); + assertEquals("incorrect number of elements", + 1, nodes.getLength()); + Element element = (Element) nodes.item(0); + id = WebServicesTestUtils.getXmlString(element, "id"); + assertTrue(ConverterUtils.toApplicationId(id) != null); + } else { + assertEquals(Status.OK, response.getClientResponseStatus()); + assertEquals(MediaType.APPLICATION_JSON_TYPE, + response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 2, json.length()); + id = json.getString("id"); + assertTrue(ConverterUtils.toApplicationId(id) != null); + } + switch (i) { + case 0: + testAppSubmit(id, acceptMedia, contentMedia); + break; + case 1: + testAppSubmitErrors(id, acceptMedia, contentMedia); + break; + } + Thread.sleep(500); + } + } + } + } + rm.stop(); + return; + } + + public void testAppSubmit(String appId, String acceptMedia, + String contentMedia) throws Exception { + + AppSubmissionInfo appInfo = new AppSubmissionInfo(); + appInfo.setApplicationId(appId); + appInfo.setApplicationName("test"); + appInfo.setPriority(3); + appInfo.setMaxAppAttempts(2); + appInfo.setQueue("testqueue"); + appInfo.setApplicationType("test-type"); + HashMap lr = + new HashMap(); + LocalResourceInfo y = new LocalResourceInfo(); + y.setUrl(new URI("http://www.test.com/file.txt")); + y.setSize(100); + y.setTimestamp(System.currentTimeMillis()); + y.setType(LocalResourceType.FILE); + y.setVisibility(LocalResourceVisibility.APPLICATION); + lr.put("example", y); + appInfo.getContainerLaunchContext().setLocalResources(lr); + appInfo.getResource().setMemory(1024); + appInfo.getResource().setvCores(1); + + ClientResponse response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + assertEquals(Status.ACCEPTED, response.getClientResponseStatus()); + assertTrue(response.getHeaders().getFirst("Location") + .endsWith("/app/" + appId)); + RMApp app = rm.getRMContext().getRMApps() + .get(ConverterUtils.toApplicationId(appId)); + assertEquals("test", app.getName()); + assertEquals(webserviceUserName, app.getUser()); + assertEquals(2, app.getMaxAppAttempts()); + assertEquals("testqueue", app.getQueue()); + assertEquals("test-type", app.getApplicationType()); + + response = this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + return; + } + + public void testAppSubmitErrors(String appId, String acceptMedia, + String contentMedia) throws Exception { + + AppSubmissionInfo appInfo = new AppSubmissionInfo(); + ClientResponse response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + appInfo.setApplicationId(appId); + response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + appInfo.setApplicationName("test"); + response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + appInfo.setPriority(3); + appInfo.setMaxAppAttempts(2); + appInfo.setQueue("testqueue"); + appInfo.setApplicationType("test-type"); + + response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + // missing local resource info + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + HashMap lr = + new HashMap(); + LocalResourceInfo y = new LocalResourceInfo(); + y.setUrl(new URI("http://www.test.com/file.txt")); + y.setSize(100); + y.setTimestamp(System.currentTimeMillis()); + y.setType(LocalResourceType.FILE); + y.setVisibility(LocalResourceVisibility.APPLICATION); + lr.put("example", y); + appInfo.getContainerLaunchContext().setLocalResources(lr); + response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + // missing resource info + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + appInfo.getResource().setMemory( + rm.getConfig().getInt( + YarnConfiguration.RM_SCHEDULER_MAXIMUM_ALLOCATION_MB, + YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB) + 1); + appInfo.getResource().setvCores(1); + response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + // bad resource info + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + appInfo.getResource().setvCores( + rm.getConfig().getInt( + YarnConfiguration.RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES, + YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES) + 1); + appInfo.getResource().setMemory(CONTAINER_MB); + response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + // bad resource info + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + appInfo.getResource().setvCores(0); + appInfo.getResource().setMemory(0); + response = + this.constructWebResource("app", appId).accept(acceptMedia) + .entity(appInfo, contentMedia).post(ClientResponse.class); + // bad resource info + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + + return; + } + + @Test + public void testAppSubmitBadJsonXML() throws Exception { + + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + amNodeManager.nodeHeartbeat(true); + String id = ""; + + AppSubmissionInfo appInfo = new AppSubmissionInfo(); + appInfo.setApplicationName("test"); + appInfo.setPriority(3); + appInfo.setMaxAppAttempts(2); + appInfo.setQueue("testqueue"); + appInfo.setApplicationType("test-type"); + HashMap lr = + new HashMap(); + LocalResourceInfo y = new LocalResourceInfo(); + y.setUrl(new URI("http://www.test.com/file.txt")); + y.setSize(100); + y.setTimestamp(System.currentTimeMillis()); + y.setType(LocalResourceType.FILE); + y.setVisibility(LocalResourceVisibility.APPLICATION); + lr.put("example", y); + appInfo.getContainerLaunchContext().setLocalResources(lr); + appInfo.getResource().setMemory(1024); + appInfo.getResource().setvCores(1); + + JAXBContext context = JAXBContext.newInstance(AppSubmissionInfo.class); + Marshaller m = context.createMarshaller(); + + ClientResponse response = this.constructWebResource("app", "id") + .accept(MediaType.APPLICATION_XML).post(ClientResponse.class); + if (rm.getConfig() + .getBoolean(YarnConfiguration.YARN_ACL_ENABLE, false) == false) { + assertEquals(Status.UNAUTHORIZED, response.getClientResponseStatus()); + return; + } + assertEquals(Status.OK, response.getClientResponseStatus()); + assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); + String xml = response.getEntity(String.class); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + InputSource is = new InputSource(); + is.setCharacterStream(new StringReader(xml)); + Document dom = db.parse(is); + NodeList nodes = dom.getElementsByTagName("newapp"); + assertEquals("incorrect number of elements", 1, nodes.getLength()); + Element element = (Element) nodes.item(0); + id = WebServicesTestUtils.getXmlString(element, "id"); + assertTrue(ConverterUtils.toApplicationId(id) != null); + appInfo.setApplicationId(id); + StringWriter sw = new StringWriter(); + m.marshal(appInfo, sw); + String body = sw.toString(); + for (int i = 0; i < 3; ++i) { + switch (i) { + case 0: + body = body.replace("FILE", "FILES12"); + break; + case 1: + body = body.replace("APPLICATION", "APPLICATION@#"); + break; + case 2: + body = ""; + break; + } + response = + this.constructWebResource("app", id) + .accept(MediaType.APPLICATION_XML) + .entity(body, MediaType.APPLICATION_XML) + .post(ClientResponse.class); + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + } + body = "{\"a\" : \"b\"}"; + response = + this.constructWebResource("app", id) + .accept(MediaType.APPLICATION_XML) + .entity(body, MediaType.APPLICATION_JSON) + .post(ClientResponse.class); + assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus()); + rm.stop(); + } +} \ No newline at end of file