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/TestRMWebServicesAppAttempts.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppAttempts.java new file mode 100644 index 00000000000..a84fdcad934 --- /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/TestRMWebServicesAppAttempts.java @@ -0,0 +1,397 @@ +/* + * 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 com.google.inject.Guice; +import com.google.inject.servlet.ServletModule; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.UniformInterfaceException; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; +import com.sun.jersey.test.framework.WebAppDescriptor; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.http.JettyUtils; +import org.apache.hadoop.yarn.api.records.ContainerState; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.server.resourcemanager.MockAM; +import org.apache.hadoop.yarn.server.resourcemanager.MockNM; +import org.apache.hadoop.yarn.server.resourcemanager.MockRM; +import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler; +import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; +import org.apache.hadoop.yarn.webapp.GuiceServletConfig; +import org.apache.hadoop.yarn.webapp.JerseyTestBase; +import org.apache.hadoop.yarn.webapp.WebServicesTestUtils; +import org.codehaus.jettison.json.JSONArray; +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 javax.ws.rs.core.MediaType; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.StringReader; +import java.util.Collection; + +import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseStatusCode; +import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.checkStringMatch; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class TestRMWebServicesAppAttempts extends JerseyTestBase { + + private static MockRM rm; + + private static final int CONTAINER_MB = 1024; + + private static class WebServletModule extends 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); + serve("/*").with(GuiceContainer.class); + } + } + + static { + GuiceServletConfig.setInjector( + Guice.createInjector(new WebServletModule())); + } + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + GuiceServletConfig.setInjector( + Guice.createInjector(new WebServletModule())); + } + + public TestRMWebServicesAppAttempts() { + 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()); + } + + @Test + public void testAppAttempts() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); + amNodeManager.nodeHeartbeat(true); + testAppAttemptsHelper(app1.getApplicationId().toString(), app1, + MediaType.APPLICATION_JSON); + rm.stop(); + } + + @Test (timeout = 20000) + public void testMultipleAppAttempts() throws 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); + 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); + rm.waitForState(am.getApplicationAttemptId(), RMAppAttemptState.FAILED); + if (numAttempt == maxAppAttempts) { + rm.waitForState(app1.getApplicationId(), RMAppState.FAILED); + break; + } + // wait for app to start a new attempt. + rm.waitForState(app1.getApplicationId(), RMAppState.ACCEPTED); + am = MockRM.launchAndRegisterAM(app1, rm, amNodeManager); + numAttempt++; + } + assertEquals("incorrect number of attempts", maxAppAttempts, + app1.getAppAttempts().values().size()); + testAppAttemptsHelper(app1.getApplicationId().toString(), app1, + MediaType.APPLICATION_JSON); + rm.stop(); + } + + @Test + public void testAppAttemptsSlash() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + RMApp app1 = rm.submitApp(CONTAINER_MB); + amNodeManager.nodeHeartbeat(true); + testAppAttemptsHelper(app1.getApplicationId().toString() + "/", app1, + MediaType.APPLICATION_JSON); + rm.stop(); + } + + @Test + public void testAppAttemptsDefault() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + RMApp app1 = rm.submitApp(CONTAINER_MB); + amNodeManager.nodeHeartbeat(true); + testAppAttemptsHelper(app1.getApplicationId().toString() + "/", app1, ""); + rm.stop(); + } + + @Test + public void testInvalidAppIdGetAttempts() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + RMApp app = rm.submitApp(CONTAINER_MB); + amNodeManager.nodeHeartbeat(true); + WebResource r = resource(); + + try { + r.path("ws").path("v1").path("cluster").path("apps") + .path("application_invalid_12").path("appattempts") + .accept(MediaType.APPLICATION_JSON) + .get(JSONObject.class); + fail("should have thrown exception on invalid appAttempt"); + } catch (UniformInterfaceException ue) { + ClientResponse response = ue.getResponse(); + + assertResponseStatusCode(ClientResponse.Status.BAD_REQUEST, + response.getStatusInfo()); + assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, + response.getType().toString()); + JSONObject msg = response.getEntity(JSONObject.class); + JSONObject exception = msg.getJSONObject("RemoteException"); + assertEquals("incorrect number of elements", 3, exception.length()); + String message = exception.getString("message"); + String type = exception.getString("exception"); + String classname = exception.getString("javaClassName"); + checkStringMatch("exception message", + "java.lang.IllegalArgumentException: Invalid ApplicationId:" + + " application_invalid_12", + message); + checkStringMatch("exception type", + "BadRequestException", type); + checkStringMatch("exception classname", + "org.apache.hadoop.yarn.webapp.BadRequestException", classname); + + } finally { + rm.stop(); + } + } + + @Test + public void testInvalidAppAttemptId() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + RMApp app = rm.submitApp(CONTAINER_MB); + amNodeManager.nodeHeartbeat(true); + WebResource r = resource(); + + try { + r.path("ws").path("v1").path("cluster").path("apps") + .path(app.getApplicationId().toString()).path("appattempts") + .path("appattempt_invalid_12_000001") + .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); + fail("should have thrown exception on invalid appAttempt"); + } catch (UniformInterfaceException ue) { + ClientResponse response = ue.getResponse(); + + assertResponseStatusCode(ClientResponse.Status.BAD_REQUEST, + response.getStatusInfo()); + assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, + response.getType().toString()); + JSONObject msg = response.getEntity(JSONObject.class); + JSONObject exception = msg.getJSONObject("RemoteException"); + assertEquals("incorrect number of elements", 3, exception.length()); + String message = exception.getString("message"); + String type = exception.getString("exception"); + String classname = exception.getString("javaClassName"); + checkStringMatch("exception message", + "java.lang.IllegalArgumentException: Invalid AppAttemptId:" + + " appattempt_invalid_12_000001", + message); + checkStringMatch("exception type", + "BadRequestException", type); + checkStringMatch("exception classname", + "org.apache.hadoop.yarn.webapp.BadRequestException", classname); + + } finally { + rm.stop(); + } + } + + @Test + public void testNonexistAppAttempts() throws Exception { + rm.start(); + 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); + fail("should have thrown exception on invalid appid"); + } catch (UniformInterfaceException ue) { + ClientResponse response = ue.getResponse(); + + assertResponseStatusCode(ClientResponse.Status.NOT_FOUND, + response.getStatusInfo()); + assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, + response.getType().toString()); + + JSONObject msg = response.getEntity(JSONObject.class); + JSONObject exception = msg.getJSONObject("RemoteException"); + assertEquals("incorrect number of elements", 3, exception.length()); + String message = exception.getString("message"); + String type = exception.getString("exception"); + String classname = exception.getString("javaClassName"); + checkStringMatch("exception message", + "java.lang.Exception: app with id: application_00000_0099 not found", + message); + checkStringMatch("exception type", + "NotFoundException", type); + checkStringMatch("exception classname", + "org.apache.hadoop.yarn.webapp.NotFoundException", classname); + } finally { + rm.stop(); + } + } + + private void testAppAttemptsHelper(String path, RMApp app, String media) + throws Exception { + WebResource r = resource(); + ClientResponse response = r.path("ws").path("v1").path("cluster") + .path("apps").path(path).path("appattempts").accept(media) + .get(ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, + response.getType().toString()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject jsonAppAttempts = json.getJSONObject("appAttempts"); + assertEquals("incorrect number of elements", 1, jsonAppAttempts.length()); + JSONArray jsonArray = jsonAppAttempts.getJSONArray("appAttempt"); + + Collection attempts = app.getAppAttempts().values(); + assertEquals("incorrect number of elements", attempts.size(), + jsonArray.length()); + + // Verify these parallel arrays are the same + int i = 0; + for (RMAppAttempt attempt : attempts) { + verifyAppAttemptsInfo(jsonArray.getJSONObject(i), attempt, app.getUser()); + ++i; + } + } + + @Test + public void testAppAttemptsXML() throws Exception { + rm.start(); + String user = "user1"; + 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); + assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8, + response.getType().toString()); + 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("appAttempts"); + assertEquals("incorrect number of elements", 1, nodes.getLength()); + NodeList attempt = dom.getElementsByTagName("appAttempt"); + assertEquals("incorrect number of elements", 1, attempt.getLength()); + verifyAppAttemptsXML(attempt, app1.getCurrentAppAttempt(), user); + rm.stop(); + } + + private void verifyAppAttemptsXML(NodeList nodes, RMAppAttempt appAttempt, + String user) { + + 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); + } + } + + private void verifyAppAttemptsInfo(JSONObject info, RMAppAttempt appAttempt, + String user) + throws Exception { + + assertEquals("incorrect number of elements", 10, info.length()); + + verifyAppAttemptInfoGeneric(appAttempt, info.getInt("id"), + info.getLong("startTime"), info.getString("containerId"), + info.getString("nodeHttpAddress"), info.getString("nodeId"), + info.getString("logsLink"), user); + } + + private void verifyAppAttemptInfoGeneric(RMAppAttempt appAttempt, int id, + long startTime, String containerId, String nodeHttpAddress, String + nodeId, + String logsLink, String user) { + + assertEquals("id doesn't match", appAttempt.getAppAttemptId() + .getAttemptId(), id); + assertEquals("startedTime doesn't match", appAttempt.getStartTime(), + startTime); + checkStringMatch("containerId", appAttempt + .getMasterContainer().getId().toString(), containerId); + checkStringMatch("nodeHttpAddress", appAttempt + .getMasterContainer().getNodeHttpAddress(), nodeHttpAddress); + checkStringMatch("nodeId", appAttempt + .getMasterContainer().getNodeId().toString(), nodeId); + assertTrue("logsLink doesn't match ", logsLink.startsWith("http://")); + assertTrue( + "logsLink doesn't contain user info", logsLink.endsWith("/" + + user)); + } +} 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/TestRMWebServicesAppCustomResourceTypes.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppCustomResourceTypes.java new file mode 100644 index 00000000000..ab4dcf889cd --- /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/TestRMWebServicesAppCustomResourceTypes.java @@ -0,0 +1,170 @@ +/* + * 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 com.google.inject.Guice; +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.WebAppDescriptor; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.server.resourcemanager.MockAM; +import org.apache.hadoop.yarn.server.resourcemanager.MockNM; +import org.apache.hadoop.yarn.server.resourcemanager.MockRM; +import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; +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.webapp.fairscheduler.CustomResourceTypesConfigurationProvider; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.BufferedClientResponse; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.JsonCustomResourceTypeTestcase; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.XmlCustomResourceTypeTestCase; +import org.apache.hadoop.yarn.util.resource.ResourceUtils; +import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; +import org.apache.hadoop.yarn.webapp.GuiceServletConfig; +import org.apache.hadoop.yarn.webapp.JerseyTestBase; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.w3c.dom.NodeList; + +import javax.ws.rs.core.MediaType; +import java.util.ArrayList; + +import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestRMWebServicesCustomResourceTypesCommons.verifyAppInfoJson; +import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestRMWebServicesCustomResourceTypesCommons.verifyAppsXML; +import static org.junit.Assert.assertEquals; + +/** + * This test verifies that custom resource types are correctly serialized to XML + * and JSON when HTTP GET request is sent to the resource: ws/v1/cluster/apps. + */ +public class TestRMWebServicesAppCustomResourceTypes extends JerseyTestBase { + + private static MockRM rm; + private static final int CONTAINER_MB = 1024; + + private static class WebServletModule extends 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); + initResourceTypes(conf); + rm = new MockRM(conf); + bind(ResourceManager.class).toInstance(rm); + serve("/*").with(GuiceContainer.class); + } + + private void initResourceTypes(Configuration conf) { + conf.set(YarnConfiguration.RM_CONFIGURATION_PROVIDER_CLASS, + CustomResourceTypesConfigurationProvider.class.getName()); + ResourceUtils.resetResourceTypes(conf); + } + } + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + createInjectorForWebServletModule(); + } + + private void createInjectorForWebServletModule() { + GuiceServletConfig + .setInjector(Guice.createInjector(new WebServletModule())); + } + + public TestRMWebServicesAppCustomResourceTypes() { + 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()); + } + + private WebResource getWebResourcePathForApp(RMApp app1, WebResource r) { + return r.path("ws").path("v1").path("cluster").path("apps") + .path(String.valueOf(app1.getApplicationId().toString())); + } + + @Test + public void testRunningAppXml() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); + MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, amNodeManager); + am1.allocate("*", 2048, 1, new ArrayList<>()); + amNodeManager.nodeHeartbeat(true); + + WebResource r = resource(); + WebResource path = getWebResourcePathForApp(app1, r); + ClientResponse response = + path.accept(MediaType.APPLICATION_XML).get(ClientResponse.class); + + XmlCustomResourceTypeTestCase testCase = + new XmlCustomResourceTypeTestCase(path, + new BufferedClientResponse(response)); + testCase.verify(document -> { + NodeList appArray = document + .getElementsByTagName("app"); + assertEquals("incorrect number of app elements", 1, appArray.getLength()); + + verifyAppsXML(appArray, app1, rm); + }); + + rm.stop(); + } + + @Test + public void testRunningAppJson() throws Exception { + rm.start(); + MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); + RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); + MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, amNodeManager); + am1.allocate("*", 2048, 1, new ArrayList<>()); + amNodeManager.nodeHeartbeat(true); + + WebResource r = resource(); + WebResource path = getWebResourcePathForApp(app1, r); + ClientResponse response = + path.accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + + JsonCustomResourceTypeTestcase testCase = + new JsonCustomResourceTypeTestcase(path, + new BufferedClientResponse(response)); + testCase.verify(json -> { + try { + assertEquals("incorrect number of app elements", 1, json.length()); + JSONObject app = json.getJSONObject("app"); + verifyAppInfoJson(app, app1, rm); + } catch (JSONException e) { + throw new RuntimeException(e); + } + }); + + rm.stop(); + } +} 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 15f94e1bb00..e9fd577d8fd 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 @@ -1781,292 +1781,5 @@ public void verifyResourceRequestsGeneric(ResourceRequest request, enforceExecutionType); } - @Test - public void testAppAttempts() throws JSONException, Exception { - rm.start(); - MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); - RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); - amNodeManager.nodeHeartbeat(true); - testAppAttemptsHelper(app1.getApplicationId().toString(), app1, - MediaType.APPLICATION_JSON); - rm.stop(); - } - - @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); - 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); - rm.waitForState(am.getApplicationAttemptId(), RMAppAttemptState.FAILED); - if (numAttempt == maxAppAttempts) { - rm.waitForState(app1.getApplicationId(), RMAppState.FAILED); - break; - } - // wait for app to start a new attempt. - rm.waitForState(app1.getApplicationId(), RMAppState.ACCEPTED); - am = MockRM.launchAndRegisterAM(app1, rm, amNodeManager); - numAttempt++; - } - assertEquals("incorrect number of attempts", maxAppAttempts, - app1.getAppAttempts().values().size()); - testAppAttemptsHelper(app1.getApplicationId().toString(), app1, - MediaType.APPLICATION_JSON); - rm.stop(); - } - - @Test - public void testAppAttemptsSlash() throws JSONException, Exception { - rm.start(); - MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); - RMApp app1 = rm.submitApp(CONTAINER_MB); - amNodeManager.nodeHeartbeat(true); - testAppAttemptsHelper(app1.getApplicationId().toString() + "/", app1, - MediaType.APPLICATION_JSON); - rm.stop(); - } - - @Test - public void testAppAttemtpsDefault() throws JSONException, Exception { - rm.start(); - MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); - RMApp app1 = rm.submitApp(CONTAINER_MB); - amNodeManager.nodeHeartbeat(true); - testAppAttemptsHelper(app1.getApplicationId().toString() + "/", app1, ""); - rm.stop(); - } - - @Test - public void testInvalidAppIdGetAttempts() throws JSONException, Exception { - rm.start(); - MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); - RMApp app = rm.submitApp(CONTAINER_MB); - amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - - try { - r.path("ws").path("v1").path("cluster").path("apps") - .path("application_invalid_12").path("appattempts") - .accept(MediaType.APPLICATION_JSON) - .get(JSONObject.class); - fail("should have thrown exception on invalid appAttempt"); - } catch (UniformInterfaceException ue) { - ClientResponse response = ue.getResponse(); - - assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo()); - assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, - response.getType().toString()); - JSONObject msg = response.getEntity(JSONObject.class); - JSONObject exception = msg.getJSONObject("RemoteException"); - assertEquals("incorrect number of elements", 3, exception.length()); - String message = exception.getString("message"); - String type = exception.getString("exception"); - String classname = exception.getString("javaClassName"); - WebServicesTestUtils.checkStringMatch("exception message", - "java.lang.IllegalArgumentException: Invalid ApplicationId:" - + " application_invalid_12", - message); - WebServicesTestUtils.checkStringMatch("exception type", - "BadRequestException", type); - WebServicesTestUtils.checkStringMatch("exception classname", - "org.apache.hadoop.yarn.webapp.BadRequestException", classname); - - } finally { - rm.stop(); - } - } - - @Test - public void testInvalidAppAttemptId() throws JSONException, Exception { - rm.start(); - MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); - RMApp app = rm.submitApp(CONTAINER_MB); - amNodeManager.nodeHeartbeat(true); - WebResource r = resource(); - - try { - r.path("ws").path("v1").path("cluster").path("apps") - .path(app.getApplicationId().toString()).path("appattempts") - .path("appattempt_invalid_12_000001") - .accept(MediaType.APPLICATION_JSON).get(JSONObject.class); - fail("should have thrown exception on invalid appAttempt"); - } catch (UniformInterfaceException ue) { - ClientResponse response = ue.getResponse(); - - assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo()); - assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, - response.getType().toString()); - JSONObject msg = response.getEntity(JSONObject.class); - JSONObject exception = msg.getJSONObject("RemoteException"); - assertEquals("incorrect number of elements", 3, exception.length()); - String message = exception.getString("message"); - String type = exception.getString("exception"); - String classname = exception.getString("javaClassName"); - WebServicesTestUtils.checkStringMatch("exception message", - "java.lang.IllegalArgumentException: Invalid AppAttemptId:" - + " appattempt_invalid_12_000001", - message); - WebServicesTestUtils.checkStringMatch("exception type", - "BadRequestException", type); - WebServicesTestUtils.checkStringMatch("exception classname", - "org.apache.hadoop.yarn.webapp.BadRequestException", classname); - - } finally { - rm.stop(); - } - } - - @Test - public void testNonexistAppAttempts() throws JSONException, Exception { - rm.start(); - 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); - fail("should have thrown exception on invalid appid"); - } catch (UniformInterfaceException ue) { - ClientResponse response = ue.getResponse(); - - assertResponseStatusCode(Status.NOT_FOUND, response.getStatusInfo()); - assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, - response.getType().toString()); - - JSONObject msg = response.getEntity(JSONObject.class); - JSONObject exception = msg.getJSONObject("RemoteException"); - assertEquals("incorrect number of elements", 3, exception.length()); - String message = exception.getString("message"); - 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); - WebServicesTestUtils.checkStringMatch("exception type", - "NotFoundException", type); - WebServicesTestUtils.checkStringMatch("exception classname", - "org.apache.hadoop.yarn.webapp.NotFoundException", classname); - } finally { - rm.stop(); - } - } - - 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); - assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, - response.getType().toString()); - JSONObject json = response.getEntity(JSONObject.class); - assertEquals("incorrect number of elements", 1, json.length()); - JSONObject jsonAppAttempts = json.getJSONObject("appAttempts"); - assertEquals("incorrect number of elements", 1, jsonAppAttempts.length()); - JSONArray jsonArray = jsonAppAttempts.getJSONArray("appAttempt"); - - Collection attempts = app.getAppAttempts().values(); - assertEquals("incorrect number of elements", attempts.size(), - jsonArray.length()); - - // Verify these parallel arrays are the same - int i = 0; - for (RMAppAttempt attempt : attempts) { - verifyAppAttemptsInfo(jsonArray.getJSONObject(i), attempt, app.getUser()); - ++i; - } - } - - @Test - public void testAppAttemptsXML() throws JSONException, Exception { - rm.start(); - String user = "user1"; - 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); - assertEquals(MediaType.APPLICATION_XML_TYPE + "; " + JettyUtils.UTF_8, - response.getType().toString()); - 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("appAttempts"); - assertEquals("incorrect number of elements", 1, nodes.getLength()); - NodeList attempt = dom.getElementsByTagName("appAttempt"); - assertEquals("incorrect number of elements", 1, attempt.getLength()); - verifyAppAttemptsXML(attempt, app1.getCurrentAppAttempt(), user); - rm.stop(); - } - - public void verifyAppAttemptsXML(NodeList nodes, RMAppAttempt appAttempt, - 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); - } - } - - public void verifyAppAttemptsInfo(JSONObject info, RMAppAttempt appAttempt, - String user) - throws JSONException, Exception { - - assertEquals("incorrect number of elements", 10, info.length()); - - verifyAppAttemptInfoGeneric(appAttempt, info.getInt("id"), - 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 { - - assertEquals("id doesn't match", appAttempt.getAppAttemptId() - .getAttemptId(), id); - assertEquals("startedTime doesn't match", appAttempt.getStartTime(), - startTime); - WebServicesTestUtils.checkStringMatch("containerId", appAttempt - .getMasterContainer().getId().toString(), containerId); - WebServicesTestUtils.checkStringMatch("nodeHttpAddress", appAttempt - .getMasterContainer().getNodeHttpAddress(), nodeHttpAddress); - WebServicesTestUtils.checkStringMatch("nodeId", appAttempt - .getMasterContainer().getNodeId().toString(), nodeId); - assertTrue("logsLink doesn't match ", logsLink.startsWith("http://")); - assertTrue( - "logsLink doesn't contain user info", logsLink.endsWith("/" - + user)); - } - } 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/TestRMWebServicesAppsCustomResourceTypes.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppsCustomResourceTypes.java index 83e00567eca..bcdb7138b98 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppsCustomResourceTypes.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppsCustomResourceTypes.java @@ -25,24 +25,18 @@ import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import com.sun.jersey.test.framework.WebAppDescriptor; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.yarn.api.records.ResourceRequest; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.server.resourcemanager.MockAM; import org.apache.hadoop.yarn.server.resourcemanager.MockNM; import org.apache.hadoop.yarn.server.resourcemanager.MockRM; import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; -import org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnScheduler; 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.webapp.dao.AppInfo; + import org.apache.hadoop.yarn.server.resourcemanager.webapp.fairscheduler.CustomResourceTypesConfigurationProvider; -import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.AppInfoJsonVerifications; -import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.AppInfoXmlVerifications; import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.BufferedClientResponse; import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.JsonCustomResourceTypeTestcase; -import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.ResourceRequestsJsonVerifications; -import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.ResourceRequestsXmlVerifications; import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.XmlCustomResourceTypeTestCase; import org.apache.hadoop.yarn.util.resource.ResourceUtils; import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; @@ -54,12 +48,15 @@ import org.junit.Before; import org.junit.Test; import org.w3c.dom.Element; -import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.ws.rs.core.MediaType; import java.util.ArrayList; +import static org.apache.hadoop.yarn.server.resourcemanager.webapp + .TestRMWebServicesCustomResourceTypesCommons.verifyAppInfoJson; +import static org.apache.hadoop.yarn.server.resourcemanager.webapp + .TestRMWebServicesCustomResourceTypesCommons.verifyAppsXML; import static org.junit.Assert.assertEquals; /** @@ -116,7 +113,7 @@ public TestRMWebServicesAppsCustomResourceTypes() { } @Test - public void testRunningAppXml() throws Exception { + public void testRunningAppsXml() throws Exception { rm.start(); MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); @@ -140,14 +137,14 @@ public void testRunningAppXml() throws Exception { .getElementsByTagName("app"); assertEquals("incorrect number of app elements", 1, appArray.getLength()); - verifyAppsXML(appArray, app1); + verifyAppsXML(appArray, app1, rm); }); rm.stop(); } @Test - public void testRunningAppJson() throws Exception { + public void testRunningAppsJson() throws Exception { rm.start(); MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 2048); RMApp app1 = rm.submitApp(CONTAINER_MB, "testwordcount", "user1"); @@ -171,7 +168,7 @@ public void testRunningAppJson() throws Exception { JSONArray array = apps.getJSONArray("app"); assertEquals("incorrect count of app", 1, array.length()); - verifyAppInfoJson(array.getJSONObject(0), app1); + verifyAppInfoJson(array.getJSONObject(0), app1, rm); } catch (JSONException e) { throw new RuntimeException(e); } @@ -179,64 +176,4 @@ public void testRunningAppJson() throws Exception { rm.stop(); } - - private void verifyAppsXML(NodeList appArray, RMApp app) { - for (int i = 0; i < appArray.getLength(); i++) { - Element element = (Element) appArray.item(i); - AppInfoXmlVerifications.verify(element, app); - - NodeList resourceRequests = - element.getElementsByTagName("resourceRequests"); - assertEquals(1, resourceRequests.getLength()); - Node resourceRequest = resourceRequests.item(0); - ResourceRequest rr = - ((AbstractYarnScheduler) rm.getRMContext().getScheduler()) - .getApplicationAttempt( - app.getCurrentAppAttempt().getAppAttemptId()) - .getAppSchedulingInfo().getAllResourceRequests().get(0); - ResourceRequestsXmlVerifications.verifyWithCustomResourceTypes( - (Element) resourceRequest, rr, - CustomResourceTypesConfigurationProvider.getCustomResourceTypes()); - } - } - - private void verifyAppInfoJson(JSONObject info, RMApp app) throws - JSONException { - int expectedNumberOfElements = getExpectedNumberOfElements(app); - - assertEquals("incorrect number of elements", expectedNumberOfElements, - info.length()); - - AppInfoJsonVerifications.verify(info, app); - - JSONArray resourceRequests = info.getJSONArray("resourceRequests"); - JSONObject requestInfo = resourceRequests.getJSONObject(0); - ResourceRequest rr = - ((AbstractYarnScheduler) rm.getRMContext().getScheduler()) - .getApplicationAttempt(app.getCurrentAppAttempt().getAppAttemptId()) - .getAppSchedulingInfo().getAllResourceRequests().get(0); - - ResourceRequestsJsonVerifications.verifyWithCustomResourceTypes( - requestInfo, rr, - CustomResourceTypesConfigurationProvider.getCustomResourceTypes()); - } - - private int getExpectedNumberOfElements(RMApp app) { - int expectedNumberOfElements = 40 + 2; // 2 -> resourceRequests - if (app.getApplicationSubmissionContext() - .getNodeLabelExpression() != null) { - expectedNumberOfElements++; - } - - if (app.getAMResourceRequests().get(0).getNodeLabelExpression() != null) { - expectedNumberOfElements++; - } - - if (AppInfo - .getAmRPCAddressFromRMAppAttempt(app.getCurrentAppAttempt()) != null) { - expectedNumberOfElements++; - } - return expectedNumberOfElements; - } - } 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/TestRMWebServicesCustomResourceTypesCommons.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesCustomResourceTypesCommons.java new file mode 100644 index 00000000000..63ec19c3709 --- /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/TestRMWebServicesCustomResourceTypesCommons.java @@ -0,0 +1,99 @@ +/* + * 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 org.apache.hadoop.yarn.api.records.ResourceRequest; +import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler + .AbstractYarnScheduler; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.fairscheduler + .CustomResourceTypesConfigurationProvider; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.AppInfoJsonVerifications; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.AppInfoXmlVerifications; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.ResourceRequestsJsonVerifications; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.helper.ResourceRequestsXmlVerifications; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import static org.junit.Assert.assertEquals; + +public class TestRMWebServicesCustomResourceTypesCommons { + + static void verifyAppsXML(NodeList appArray, RMApp app, ResourceManager rm) { + for (int i = 0; i < appArray.getLength(); i++) { + Element element = (Element) appArray.item(i); + AppInfoXmlVerifications.verify(element, app); + + NodeList resourceRequests = + element.getElementsByTagName("resourceRequests"); + assertEquals(1, resourceRequests.getLength()); + Node resourceRequest = resourceRequests.item(0); + ResourceRequest rr = + ((AbstractYarnScheduler) rm.getRMContext().getScheduler()) + .getApplicationAttempt( + app.getCurrentAppAttempt().getAppAttemptId()) + .getAppSchedulingInfo().getAllResourceRequests().get(0); + ResourceRequestsXmlVerifications.verifyWithCustomResourceTypes( + (Element) resourceRequest, rr, + CustomResourceTypesConfigurationProvider.getCustomResourceTypes()); + } + } + + static void verifyAppInfoJson(JSONObject info, RMApp app, ResourceManager rm) + throws JSONException { + int expectedNumberOfElements = getExpectedNumberOfElements(app); + + assertEquals("incorrect number of elements", expectedNumberOfElements, + info.length()); + + AppInfoJsonVerifications.verify(info, app); + + JSONArray resourceRequests = info.getJSONArray("resourceRequests"); + JSONObject requestInfo = resourceRequests.getJSONObject(0); + ResourceRequest rr = + ((AbstractYarnScheduler) rm.getRMContext().getScheduler()) + .getApplicationAttempt(app.getCurrentAppAttempt().getAppAttemptId()) + .getAppSchedulingInfo().getAllResourceRequests().get(0); + + ResourceRequestsJsonVerifications.verifyWithCustomResourceTypes(requestInfo, + rr, CustomResourceTypesConfigurationProvider.getCustomResourceTypes()); + } + + static int getExpectedNumberOfElements(RMApp app) { + int expectedNumberOfElements = 40 + 2; // 2 -> resourceRequests + if (app.getApplicationSubmissionContext() + .getNodeLabelExpression() != null) { + expectedNumberOfElements++; + } + + if (app.getAMResourceRequests().get(0).getNodeLabelExpression() != null) { + expectedNumberOfElements++; + } + + if (AppInfo + .getAmRPCAddressFromRMAppAttempt(app.getCurrentAppAttempt()) != null) { + expectedNumberOfElements++; + } + return expectedNumberOfElements; + } +} 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/helper/BufferedClientResponse.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/BufferedClientResponse.java index a8990ca695a..c034f4e7dd2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/BufferedClientResponse.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/BufferedClientResponse.java @@ -24,6 +24,7 @@ import com.sun.jersey.api.client.UniformInterfaceException; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import java.io.IOException; /** @@ -54,4 +55,12 @@ public BufferedClientResponse(ClientResponse response) { public MediaType getType() { return response.getType(); } + + public int getStatus() { + return response.getStatus(); + } + + public Response.StatusType getStatusInfo() { + return response.getStatusInfo(); + } } 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/helper/JsonCustomResourceTypeTestcase.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/JsonCustomResourceTypeTestcase.java index 9d6a111d7ac..2b8d08d398c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/JsonCustomResourceTypeTestcase.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/JsonCustomResourceTypeTestcase.java @@ -50,10 +50,19 @@ public JsonCustomResourceTypeTestcase(WebResource path, BufferedClientResponse response) { this.path = path; + verifyStatus(response); this.response = response; this.parsedResponse = response.getEntity(JSONObject.class); } + private void verifyStatus(BufferedClientResponse response) { + String responseStr = response.getEntity(String.class); + assertEquals("HTTP status should be 200, " + + "status info: " + response.getStatusInfo() + + " response as string: " + responseStr, + 200, response.getStatus()); + } + public void verify(Consumer verifier) { assertEquals(MediaType.APPLICATION_JSON_TYPE + "; " + JettyUtils.UTF_8, response.getType().toString()); 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/helper/XmlCustomResourceTypeTestCase.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/XmlCustomResourceTypeTestCase.java index 29260aad1df..0ad92d20bb5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/XmlCustomResourceTypeTestCase.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/helper/XmlCustomResourceTypeTestCase.java @@ -59,9 +59,18 @@ public XmlCustomResourceTypeTestCase(WebResource path, BufferedClientResponse response) { this.path = path; + verifyStatus(response); this.response = response; } + private void verifyStatus(BufferedClientResponse response) { + String responseStr = response.getEntity(String.class); + assertEquals("HTTP status should be 200, " + + "status info: " + response.getStatusInfo() + + " response as string: " + responseStr, + 200, response.getStatus()); + } + public void verify(Consumer verifier) { assertEquals(MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8, response.getType().toString());