TestApiServiceClient.java
/*
* 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.service.client;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.Lists;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.apache.hadoop.yarn.service.exceptions.LauncherExitCodes.*;
/**
* Test case for CLI to API Service.
*
*/
public class TestApiServiceClient {
private static ApiServiceClient asc;
private static ApiServiceClient badAsc;
private static Server server;
/**
* A mocked version of API Service for testing purpose.
*
*/
@SuppressWarnings("serial")
public static class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("Get was called");
if (req.getPathInfo() != null
&& req.getPathInfo().contains("nonexistent-app")) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
} else {
resp.setStatus(HttpServletResponse.SC_OK);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setStatus(HttpServletResponse.SC_OK);
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setStatus(HttpServletResponse.SC_OK);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setStatus(HttpServletResponse.SC_OK);
}
}
@BeforeAll
public static void setup() throws Exception {
server = new Server(8088);
((QueuedThreadPool)server.getThreadPool()).setMaxThreads(20);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/app");
server.setHandler(context);
context.addServlet(new ServletHolder(TestServlet.class), "/*");
((ServerConnector)server.getConnectors()[0]).setHost("localhost");
server.start();
Configuration conf = new Configuration();
conf.set("yarn.resourcemanager.webapp.address",
"localhost:8088");
asc = new ApiServiceClient();
asc.serviceInit(conf);
Configuration conf2 = new Configuration();
conf2.set("yarn.resourcemanager.webapp.address",
"localhost:8089");
badAsc = new ApiServiceClient();
badAsc.serviceInit(conf2);
}
@AfterAll
public static void tearDown() throws Exception {
server.stop();
}
@Test
void testGetRMWebAddress() throws Exception {
Configuration conf = new Configuration();
conf.setBoolean(YarnConfiguration.RM_HA_ENABLED, true);
conf.set(YarnConfiguration.RM_HA_IDS, "rm1");
conf.set(YarnConfiguration.RM_HA_ID, "rm1");
conf.set("yarn.resourcemanager.webapp.address.rm1", "localhost:0");
ApiServiceClient asc1 = new ApiServiceClient(conf);
boolean exceptionCaught = false;
String diagnosticsMsg = null;
try {
String rmWebAddress = asc1.getRMWebAddress();
} catch (IOException e) {
exceptionCaught = true;
diagnosticsMsg = e.getMessage();
}
assertTrue(exceptionCaught, "ApiServiceClient failed to throw exception");
assertTrue(diagnosticsMsg.contains("Error connecting to localhost:0"),
"Exception Message does not match");
}
@Test
void testLaunch() {
String fileName = "target/test-classes/example-app.json";
String appName = "example-app";
long lifetime = 3600L;
String queue = "default";
try {
int result = asc.actionLaunch(fileName, appName, lifetime, queue);
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testBadLaunch() {
String fileName = "unknown_file";
String appName = "unknown_app";
long lifetime = 3600L;
String queue = "default";
try {
int result = badAsc.actionLaunch(fileName, appName, lifetime, queue);
assertEquals(EXIT_EXCEPTION_THROWN, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testStatus() {
String appName = "nonexistent-app";
try {
String result = asc.getStatusString(appName);
assertEquals(" Service " + appName + " not found", result, "Status reponse don't match");
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testStop() {
String appName = "example-app";
try {
int result = asc.actionStop(appName);
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testBadStop() {
String appName = "unknown_app";
try {
int result = badAsc.actionStop(appName);
assertEquals(EXIT_EXCEPTION_THROWN, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testStart() {
String appName = "example-app";
try {
int result = asc.actionStart(appName);
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testBadStart() {
String appName = "unknown_app";
try {
int result = badAsc.actionStart(appName);
assertEquals(EXIT_EXCEPTION_THROWN, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testSave() {
String fileName = "target/test-classes/example-app.json";
String appName = "example-app";
long lifetime = 3600L;
String queue = "default";
try {
int result = asc.actionSave(fileName, appName, lifetime, queue);
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testBadSave() {
String fileName = "unknown_file";
String appName = "unknown_app";
long lifetime = 3600L;
String queue = "default";
try {
int result = badAsc.actionSave(fileName, appName, lifetime, queue);
assertEquals(EXIT_EXCEPTION_THROWN, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testFlex() {
String appName = "example-app";
HashMap<String, String> componentCounts = new HashMap<String, String>();
try {
int result = asc.actionFlex(appName, componentCounts);
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testBadFlex() {
String appName = "unknown_app";
HashMap<String, String> componentCounts = new HashMap<String, String>();
try {
int result = badAsc.actionFlex(appName, componentCounts);
assertEquals(EXIT_EXCEPTION_THROWN, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testDestroy() {
String appName = "example-app";
try {
int result = asc.actionDestroy(appName);
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testBadDestroy() {
String appName = "unknown_app";
try {
int result = badAsc.actionDestroy(appName);
assertEquals(EXIT_EXCEPTION_THROWN, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testInitiateServiceUpgrade() {
String appName = "example-app";
String upgradeFileName = "target/test-classes/example-app.json";
try {
int result = asc.initiateUpgrade(appName, upgradeFileName, false);
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testInstancesUpgrade() {
String appName = "example-app";
try {
int result = asc.actionUpgradeInstances(appName, Lists.newArrayList(
"comp-1", "comp-2"));
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testComponentsUpgrade() {
String appName = "example-app";
try {
int result = asc.actionUpgradeComponents(appName, Lists.newArrayList(
"comp"));
assertEquals(EXIT_SUCCESS, result);
} catch (IOException | YarnException e) {
fail();
}
}
@Test
void testNoneSecureApiClient() throws IOException {
String url = asc.getServicePath("/foobar");
assertTrue(url.contains("user.name"),
"User.name flag is missing in service path.");
assertTrue(url.contains(System.getProperty("user.name")),
"User.name flag is not matching JVM user.");
}
}