/** * 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.mapreduce.v2.app.webapp; import static org.junit.Assert.assertEquals; import java.io.StringReader; import java.util.Enumeration; import java.util.Map; import java.util.Properties; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.ws.rs.core.MediaType; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.mapreduce.v2.api.records.JobId; import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptId; import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptState; import org.apache.hadoop.mapreduce.v2.app.AppContext; import org.apache.hadoop.mapreduce.v2.app.MockAppContext; import org.apache.hadoop.mapreduce.v2.app.job.Job; import org.apache.hadoop.mapreduce.v2.app.job.Task; import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt; import org.apache.hadoop.mapreduce.v2.util.MRApps; import org.apache.hadoop.security.authentication.server.AuthenticationFilter; import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler; import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; import org.apache.hadoop.yarn.webapp.WebServicesTestUtils; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.junit.Before; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import com.sun.jersey.test.framework.JerseyTest; import com.sun.jersey.test.framework.WebAppDescriptor; /** * Test the app master web service Rest API for getting task attempts, a * specific task attempt, and task attempt counters * * /ws/v1/mapreduce/jobs/{jobid}/tasks/{taskid}/attempts/{attemptid}/state */ public class TestAMWebServicesAttempt extends JerseyTest { private static Configuration conf = new Configuration(); private static AppContext appContext; private String webserviceUserName = "testuser"; private Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { appContext = new MockAppContext(0, 1, 2, 1); bind(JAXBContextResolver.class); bind(AMWebServices.class); bind(GenericExceptionHandler.class); bind(AppContext.class).toInstance(appContext); bind(Configuration.class).toInstance(conf); serve("/*").with(GuiceContainer.class); filter("/*").through(TestRMCustomAuthFilter.class); } }); @Singleton public static 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; } } public class GuiceServletConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return injector; } } @Before @Override public void setUp() throws Exception { super.setUp(); } public TestAMWebServicesAttempt() { super(new WebAppDescriptor.Builder( "org.apache.hadoop.mapreduce.v2.app.webapp") .contextListenerClass(GuiceServletConfig.class) .filterClass(com.google.inject.servlet.GuiceFilter.class) .contextPath("jersey-guice-filter").servletPath("/").build()); } @Test public void testGetTaskAttemptIdState() throws Exception { WebResource r = resource(); Map<JobId, Job> jobsMap = appContext.getAllJobs(); for (JobId id : jobsMap.keySet()) { String jobId = MRApps.toString(id); for (Task task : jobsMap.get(id).getTasks().values()) { String tid = MRApps.toString(task.getID()); for (TaskAttempt att : task.getAttempts().values()) { TaskAttemptId attemptid = att.getID(); String attid = MRApps.toString(attemptid); ClientResponse response = r.path("ws").path("v1").path("mapreduce") .path("jobs").path(jobId).path("tasks").path(tid) .path("attempts").path(attid).path("state") .queryParam("user.name", webserviceUserName) .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()); assertEquals(att.getState().toString(), json.get("state")); } } } } @Test public void testGetTaskAttemptIdXMLState() throws Exception { WebResource r = resource(); Map<JobId, Job> jobsMap = appContext.getAllJobs(); for (JobId id : jobsMap.keySet()) { String jobId = MRApps.toString(id); for (Task task : jobsMap.get(id).getTasks().values()) { String tid = MRApps.toString(task.getID()); for (TaskAttempt att : task.getAttempts().values()) { TaskAttemptId attemptid = att.getID(); String attid = MRApps.toString(attemptid); ClientResponse response = r.path("ws").path("v1").path("mapreduce") .path("jobs").path(jobId).path("tasks").path(tid) .path("attempts").path(attid).path("state") .queryParam("user.name", webserviceUserName) .accept(MediaType.APPLICATION_XML).get(ClientResponse.class); 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("jobTaskAttemptState"); assertEquals(1, nodes.getLength()); String state = WebServicesTestUtils.getXmlString( (Element) nodes.item(0), "state"); assertEquals(att.getState().toString(), state); } } } } @Test public void testPutTaskAttemptIdState() throws Exception { WebResource r = resource(); Map<JobId, Job> jobsMap = appContext.getAllJobs(); for (JobId id : jobsMap.keySet()) { String jobId = MRApps.toString(id); for (Task task : jobsMap.get(id).getTasks().values()) { String tid = MRApps.toString(task.getID()); for (TaskAttempt att : task.getAttempts().values()) { TaskAttemptId attemptid = att.getID(); String attid = MRApps.toString(attemptid); ClientResponse response = r.path("ws").path("v1").path("mapreduce") .path("jobs").path(jobId).path("tasks").path(tid) .path("attempts").path(attid).path("state") .queryParam("user.name", webserviceUserName) .accept(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON) .put(ClientResponse.class, "{\"state\":\"KILLED\"}"); assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); JSONObject json = response.getEntity(JSONObject.class); assertEquals("incorrect number of elements", 1, json.length()); assertEquals(TaskAttemptState.KILLED.toString(), json.get("state")); } } } } @Test public void testPutTaskAttemptIdXMLState() throws Exception { WebResource r = resource(); Map<JobId, Job> jobsMap = appContext.getAllJobs(); for (JobId id : jobsMap.keySet()) { String jobId = MRApps.toString(id); for (Task task : jobsMap.get(id).getTasks().values()) { String tid = MRApps.toString(task.getID()); for (TaskAttempt att : task.getAttempts().values()) { TaskAttemptId attemptid = att.getID(); String attid = MRApps.toString(attemptid); ClientResponse response = r.path("ws").path("v1").path("mapreduce") .path("jobs").path(jobId).path("tasks").path(tid) .path("attempts").path(attid).path("state") .queryParam("user.name", webserviceUserName) .accept(MediaType.APPLICATION_XML_TYPE) .type(MediaType.APPLICATION_XML_TYPE) .put(ClientResponse.class, "<jobTaskAttemptState><state>KILLED" + "</state></jobTaskAttemptState>"); 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("jobTaskAttemptState"); assertEquals(1, nodes.getLength()); String state = WebServicesTestUtils.getXmlString( (Element) nodes.item(0), "state"); assertEquals(TaskAttemptState.KILLED.toString(), state); } } } } }