blob: 3328ae6afc55fbcd270dd924d41a49aee4948343 [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.slider.server.appmaster.web.rest.agent;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.common.tools.PortScanner;
import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.core.conf.MapOperations;
import org.apache.slider.core.exceptions.SliderException;
import org.apache.slider.server.appmaster.management.MetricsAndMonitoring;
import org.apache.slider.server.appmaster.model.mock.MockAppState;
import org.apache.slider.server.appmaster.model.mock.MockFactory;
import org.apache.slider.server.appmaster.model.mock.MockProviderService;
import org.apache.slider.server.appmaster.model.mock.MockClusterServices;
import org.apache.slider.server.appmaster.state.AppState;
import org.apache.slider.server.appmaster.state.AppStateBindingInfo;
import org.apache.slider.server.appmaster.state.ProviderAppState;
import org.apache.slider.server.appmaster.state.SimpleReleaseSelector;
import org.apache.slider.server.appmaster.web.WebAppApi;
import org.apache.slider.server.appmaster.web.WebAppApiImpl;
import org.apache.slider.server.appmaster.web.rest.RestPaths;
import org.apache.slider.server.services.security.CertificateManager;
import org.apache.slider.server.services.security.SecurityUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.core.MediaType;
import java.io.File;
import java.net.URI;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class TestAMAgentWebServices {
static CertificateManager certificateManager;
static {
//for localhost testing only
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
return hostname.equals("localhost");
}
});
}
protected static final Logger log =
LoggerFactory.getLogger(TestAMAgentWebServices.class);
public static final String AGENT_URL =
"https://localhost:${PORT}/ws/v1/slider/agents/";
public static final int MIN_PORT = 50000;
public static final int MAX_PORT = 50050;
static MockFactory factory = new MockFactory();
private static WebAppApi slider;
private static FileSystem fs;
private AgentWebApp webApp;
private String base_url;
@BeforeClass
public static void setupClass() throws SliderException {
MapOperations configMap = new MapOperations();
SecurityUtils.initializeSecurityParameters(configMap, true);
certificateManager = new CertificateManager();
certificateManager.initialize(configMap);
String keystoreFile = SecurityUtils.getSecurityDir() + File.separator +
SliderKeys.KEYSTORE_FILE_NAME;
String password = SecurityUtils.getKeystorePass();
System.setProperty("javax.net.ssl.trustStore", keystoreFile);
System.setProperty("javax.net.ssl.trustStorePassword", password);
System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
}
@Before
public void setUp() throws Exception {
YarnConfiguration conf = SliderUtils.createConfiguration();
fs = FileSystem.get(new URI("file:///"), conf);
AppState appState = null;
File historyWorkDir = new File("target/history", "TestAMAgentWebServices");
Path historyPath = new Path(historyWorkDir.toURI());
fs.delete(historyPath, true);
appState = new MockAppState(new MockClusterServices());
AppStateBindingInfo binding = new AppStateBindingInfo();
binding.instanceDefinition = factory.newInstanceDefinition(0, 0, 0);
binding.roles = MockFactory.ROLES;
binding.fs = fs;
binding.historyPath = historyPath;
appState.buildInstance(binding);
ProviderAppState providerAppState = new ProviderAppState("undefined",
appState);
slider = new WebAppApiImpl(providerAppState,
new MockProviderService(), null, null, null,
null, null, null);
MapOperations compOperations = new MapOperations();
PortScanner portScanner = new PortScanner();
portScanner.setPortRange(Integer.toString(MIN_PORT) + "-" + Integer.toString(MAX_PORT));
webApp = AgentWebApp.$for(AgentWebApp.BASE_PATH, slider,
RestPaths.WS_AGENT_CONTEXT_ROOT)
.withComponentConfig(compOperations)
.withPort(portScanner.getAvailablePort())
.withSecuredPort(portScanner.getAvailablePort())
.start();
base_url = AGENT_URL.replace("${PORT}",
Integer.toString(webApp.getSecuredPort()));
}
@After
public void tearDown () throws Exception {
IOUtils.closeStream(webApp);
webApp = null;
}
public TestAMAgentWebServices() {
}
@Test
public void testRegistration() throws Exception {
RegistrationResponse response;
Client client = createTestClient();
WebResource webResource = client.resource(base_url + "test/register");
response = webResource.type(MediaType.APPLICATION_JSON)
.post(RegistrationResponse.class, createDummyJSONRegister());
assertEquals(RegistrationStatus.OK, response.getResponseStatus());
}
protected Client createTestClient() {
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
return Client.create(clientConfig);
}
@Test
public void testHeartbeat() throws Exception {
HeartBeatResponse response;
Client client = createTestClient();
WebResource webResource = client.resource(base_url + "test/heartbeat");
response = webResource.type(MediaType.APPLICATION_JSON)
.post(HeartBeatResponse.class, createDummyHeartBeat());
assertEquals(response.getResponseId(), 0L);
}
@Test
public void testHeadURL() throws Exception {
Client client = createTestClient();
WebResource webResource = client.resource(base_url);
ClientResponse response = webResource.type(MediaType.APPLICATION_JSON)
.head();
assertEquals(200, response.getStatus());
}
@Test
public void testAllowedPortRange() throws Exception {
assertTrue(webApp.getPort() >= MIN_PORT && webApp.getPort() <= MAX_PORT);
}
@Test
public void testAllowedSecurePortRange() throws Exception {
assertTrue(webApp.getSecuredPort() >= MIN_PORT && webApp.getSecuredPort() <= MAX_PORT);
}
// @Test
// public void testSleepForAWhile() throws Throwable {
// log.info("Agent is running at {}", base_url);
// Thread.sleep(60 * 1000);
// }
public static void testCleanupSecurityDir() throws Exception {
// Since initialization is done without setting ssl.server.keystore.location
// the security dir is created in temp file system
String securityDir = SecurityUtils.getSecurityDir();
// validate that the folder exists
File securityDirFile = new File(securityDir);
assertTrue("securityDir " + securityDir + " should exist",
securityDirFile.exists());
// call cleanup now and it should be gone
SecurityUtils.cleanupSecurityDir();
// validate that the folder does not exist anymore
assertFalse("securityDir " + securityDir + " should have been deleted",
securityDirFile.exists());
}
private Register createDummyJSONRegister() {
Register register = new Register();
register.setResponseId(-1);
register.setTimestamp(System.currentTimeMillis());
register.setLabel("dummyHost");
return register;
}
private HeartBeat createDummyHeartBeat() {
HeartBeat json = new HeartBeat();
json.setResponseId(-1);
json.setTimestamp(System.currentTimeMillis());
json.setHostname("dummyHost");
return json;
}
@AfterClass
public static void tearDownClass() throws Exception{
testCleanupSecurityDir();
// Path directory = Paths.get(SecurityUtils.getSecurityDir());
// Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
// @Override
// public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
// throws IOException {
// Files.delete(file);
// return FileVisitResult.CONTINUE;
// }
//
// @Override
// public FileVisitResult postVisitDirectory(Path dir, IOException exc)
// throws IOException {
// Files.delete(dir);
// return FileVisitResult.CONTINUE;
// }
//
// });
}
}