blob: 72c6e2f11135aaaa68d6f4fb66660585b05fd6d3 [file] [log] [blame]
/*
* 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;
import static org.junit.Assert.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.service.api.records.Artifact;
import org.apache.hadoop.yarn.service.api.records.Artifact.TypeEnum;
import org.apache.hadoop.yarn.service.api.records.Component;
import org.apache.hadoop.yarn.service.api.records.Resource;
import org.apache.hadoop.yarn.service.api.records.Service;
import org.apache.hadoop.yarn.service.api.records.ServiceState;
import org.apache.hadoop.yarn.service.api.records.ServiceStatus;
import org.apache.hadoop.yarn.service.client.ServiceClient;
import org.apache.hadoop.yarn.service.webapp.ApiServer;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
/**
* Test case for ApiServer REST API.
*
*/
public class TestApiServer {
private ApiServer apiServer;
private HttpServletRequest request;
@Before
public void setup() throws Exception {
request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRemoteUser())
.thenReturn(System.getProperty("user.name"));
ServiceClient mockServerClient = new ServiceClientTest();
Configuration conf = new Configuration();
conf.set("yarn.api-service.service.client.class",
ServiceClientTest.class.getName());
apiServer = new ApiServer(conf);
apiServer.setServiceClient(mockServerClient);
}
@Test
public void testPathAnnotation() {
assertNotNull(this.apiServer.getClass().getAnnotation(Path.class));
assertTrue("The controller has the annotation Path",
this.apiServer.getClass().isAnnotationPresent(Path.class));
final Path path = this.apiServer.getClass()
.getAnnotation(Path.class);
assertEquals("The path has /v1 annotation", "/v1", path.value());
}
@Test
public void testGetVersion() {
final Response actual = apiServer.getVersion();
assertEquals("Version number is", Response.ok().build().getStatus(),
actual.getStatus());
}
@Test
public void testBadCreateService() {
Service service = new Service();
// Test for invalid argument
final Response actual = apiServer.createService(request, service);
assertEquals("Create service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testGoodCreateService() throws Exception {
String json = "{\"auths\": "
+ "{\"https://index.docker.io/v1/\": "
+ "{\"auth\": \"foobarbaz\"},"
+ "\"registry.example.com\": "
+ "{\"auth\": \"bazbarfoo\"}}}";
File dockerTmpDir = new File("target", "docker-tmp");
FileUtils.deleteQuietly(dockerTmpDir);
dockerTmpDir.mkdirs();
String dockerConfig = dockerTmpDir + "/config.json";
BufferedWriter bw = new BufferedWriter(new FileWriter(dockerConfig));
bw.write(json);
bw.close();
Service service = new Service();
service.setName("jenkins");
service.setVersion("v1");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("jenkins");
c.setNumberOfContainers(1L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
final Response actual = apiServer.createService(request, service);
assertEquals("Create service is ",
Response.status(Status.ACCEPTED).build().getStatus(),
actual.getStatus());
}
@Test
public void testInternalServerErrorDockerClientConfigMissingCreateService() {
Service service = new Service();
service.setName("jenkins");
service.setVersion("v1");
service.setDockerClientConfig("/does/not/exist/config.json");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<>();
Component c = new Component();
c.setName("jenkins");
c.setNumberOfContainers(1L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
final Response actual = apiServer.createService(request, service);
assertEquals("Create service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testBadGetService() {
final Response actual = apiServer.getService(request, "no-jenkins");
assertEquals("Get service is ",
Response.status(Status.NOT_FOUND).build().getStatus(),
actual.getStatus());
}
@Test
public void testBadGetService2() {
final Response actual = apiServer.getService(request, null);
assertEquals("Get service is ",
Response.status(Status.NOT_FOUND).build().getStatus(),
actual.getStatus());
}
@Test
public void testGoodGetService() {
final Response actual = apiServer.getService(request, "jenkins");
assertEquals("Get service is ",
Response.status(Status.OK).build().getStatus(), actual.getStatus());
}
@Test
public void testBadDeleteService() {
final Response actual = apiServer.deleteService(request, "no-jenkins");
assertEquals("Delete service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testBadDeleteService2() {
final Response actual = apiServer.deleteService(request, null);
assertEquals("Delete service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testBadDeleteService3() {
final Response actual = apiServer.deleteService(request,
"jenkins-doesn't-exist");
assertEquals("Delete service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testBadDeleteService4() {
final Response actual = apiServer.deleteService(request,
"jenkins-error-cleaning-registry");
assertEquals("Delete service is ",
Response.status(Status.INTERNAL_SERVER_ERROR).build().getStatus(),
actual.getStatus());
}
@Test
public void testGoodDeleteService() {
final Response actual = apiServer.deleteService(request, "jenkins");
assertEquals("Delete service is ",
Response.status(Status.OK).build().getStatus(), actual.getStatus());
}
@Test
public void testDeleteStoppedService() {
final Response actual = apiServer.deleteService(request,
"jenkins-already-stopped");
assertEquals("Delete service is ",
Response.status(Status.OK).build().getStatus(), actual.getStatus());
}
@Test
public void testDecreaseContainerAndStop() {
Service service = new Service();
service.setState(ServiceState.STOPPED);
service.setName("jenkins");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("jenkins");
c.setNumberOfContainers(0L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
final Response actual = apiServer.updateService(request, "jenkins",
service);
assertEquals("update service is ",
Response.status(Status.OK).build().getStatus(), actual.getStatus());
}
@Test
public void testBadDecreaseContainerAndStop() {
Service service = new Service();
service.setState(ServiceState.STOPPED);
service.setName("no-jenkins");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("no-jenkins");
c.setNumberOfContainers(-1L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
System.out.println("before stop");
final Response actual = apiServer.updateService(request, "no-jenkins",
service);
assertEquals("flex service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testIncreaseContainersAndStart() {
Service service = new Service();
service.setState(ServiceState.STARTED);
service.setName("jenkins");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("jenkins");
c.setNumberOfContainers(2L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
final Response actual = apiServer.updateService(request, "jenkins",
service);
assertEquals("flex service is ",
Response.status(Status.OK).build().getStatus(), actual.getStatus());
}
@Test
public void testBadStartServices() {
Service service = new Service();
service.setState(ServiceState.STARTED);
service.setName("no-jenkins");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("jenkins");
c.setNumberOfContainers(2L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
final Response actual = apiServer.updateService(request, "no-jenkins",
service);
assertEquals("start service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testGoodStartServices() {
Service service = new Service();
service.setState(ServiceState.STARTED);
service.setName("jenkins");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("jenkins");
c.setNumberOfContainers(2L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
final Response actual = apiServer.updateService(request, "jenkins",
service);
assertEquals("start service is ",
Response.status(Status.OK).build().getStatus(), actual.getStatus());
}
@Test
public void testBadStopServices() {
Service service = new Service();
service.setState(ServiceState.STOPPED);
service.setName("no-jenkins");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("no-jenkins");
c.setNumberOfContainers(-1L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
System.out.println("before stop");
final Response actual = apiServer.updateService(request, "no-jenkins",
service);
assertEquals("stop service is ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
}
@Test
public void testGoodStopServices() {
Service service = new Service();
service.setState(ServiceState.STOPPED);
service.setName("jenkins");
System.out.println("before stop");
final Response actual = apiServer.updateService(request, "jenkins",
service);
assertEquals("stop service is ",
Response.status(Status.OK).build().getStatus(), actual.getStatus());
}
@Test
public void testBadSecondStopServices() throws Exception {
Service service = new Service();
service.setState(ServiceState.STOPPED);
service.setName("jenkins-second-stop");
// simulates stop on an already stopped service
System.out.println("before second stop");
final Response actual = apiServer.updateService(request,
"jenkins-second-stop", service);
assertEquals("stop service should have thrown 400 Bad Request: ",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
ServiceStatus serviceStatus = (ServiceStatus) actual.getEntity();
assertEquals("Stop service should have failed with service already stopped",
"Service jenkins-second-stop is already stopped",
serviceStatus.getDiagnostics());
}
@Test
public void testUpdateService() {
Service service = new Service();
service.setState(ServiceState.STARTED);
service.setName("no-jenkins");
Artifact artifact = new Artifact();
artifact.setType(TypeEnum.DOCKER);
artifact.setId("jenkins:latest");
Resource resource = new Resource();
resource.setCpus(1);
resource.setMemory("2048");
List<Component> components = new ArrayList<Component>();
Component c = new Component();
c.setName("no-jenkins");
c.setNumberOfContainers(-1L);
c.setArtifact(artifact);
c.setLaunchCommand("");
c.setResource(resource);
components.add(c);
service.setComponents(components);
System.out.println("before stop");
final Response actual = apiServer.updateService(request, "no-jenkins",
service);
assertEquals("update service is ",
Response.status(Status.BAD_REQUEST)
.build().getStatus(), actual.getStatus());
}
@Test
public void testUpdateComponent() {
Response actual = apiServer.updateComponent(request, "jenkins",
"jenkins-master", null);
ServiceStatus serviceStatus = (ServiceStatus) actual.getEntity();
assertEquals("Update component should have failed with 400 bad request",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
assertEquals("Update component should have failed with no data error",
"No component data provided", serviceStatus.getDiagnostics());
Component comp = new Component();
actual = apiServer.updateComponent(request, "jenkins", "jenkins-master",
comp);
serviceStatus = (ServiceStatus) actual.getEntity();
assertEquals("Update component should have failed with 400 bad request",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
assertEquals("Update component should have failed with no count error",
"No container count provided", serviceStatus.getDiagnostics());
comp.setNumberOfContainers(-1L);
actual = apiServer.updateComponent(request, "jenkins", "jenkins-master",
comp);
serviceStatus = (ServiceStatus) actual.getEntity();
assertEquals("Update component should have failed with 400 bad request",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
assertEquals("Update component should have failed with no count error",
"Invalid number of containers specified -1", serviceStatus.getDiagnostics());
comp.setName("jenkins-slave");
comp.setNumberOfContainers(1L);
actual = apiServer.updateComponent(request, "jenkins", "jenkins-master",
comp);
serviceStatus = (ServiceStatus) actual.getEntity();
assertEquals("Update component should have failed with 400 bad request",
Response.status(Status.BAD_REQUEST).build().getStatus(),
actual.getStatus());
assertEquals(
"Update component should have failed with component name mismatch "
+ "error",
"Component name in the request object (jenkins-slave) does not match "
+ "that in the URI path (jenkins-master)",
serviceStatus.getDiagnostics());
}
}