You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2015/11/11 06:13:44 UTC
ambari git commit: AMBARI-13752. Add a functional test to create a
local ambari server and test it's status using an API call. (Nahappan
Somasundaram via swagle)
Repository: ambari
Updated Branches:
refs/heads/trunk 975c0bc44 -> d49cc72e9
AMBARI-13752. Add a functional test to create a local ambari server and test it's status using an API call. (Nahappan Somasundaram via swagle)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d49cc72e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d49cc72e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d49cc72e
Branch: refs/heads/trunk
Commit: d49cc72e92a72596571061622aacb3c5b5721200
Parents: 975c0bc
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Tue Nov 10 21:13:38 2015 -0800
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Tue Nov 10 21:13:38 2015 -0800
----------------------------------------------------------------------
.../server/configuration/Configuration.java | 9 ++
.../ambari/server/controller/AmbariServer.java | 96 ++++++-----
.../server/LocalAmbariServer.java | 120 ++++++++++++++
.../server/StartStopServerTest.java | 159 +++++++++++++++++++
4 files changed, 343 insertions(+), 41 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/d49cc72e/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index e5e2c90..12f6bca 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -100,6 +100,7 @@ public class Configuration {
public static final String API_GZIP_COMPRESSION_ENABLED_KEY = "api.gzip.compression.enabled";
public static final String API_GZIP_MIN_COMPRESSION_SIZE_KEY = "api.gzip.compression.min.size";
public static final String AGENT_API_GZIP_COMPRESSION_ENABLED_KEY = "agent.api.gzip.compression.enabled";
+ public static final String AGENT_USE_SSL = "agent.ssl";
public static final String SRVR_TWO_WAY_SSL_KEY = "security.server.two_way_ssl";
public static final String SRVR_TWO_WAY_SSL_PORT_KEY = "security.server.two_way_ssl.port";
public static final String SRVR_ONE_WAY_SSL_PORT_KEY = "security.server.one_way_ssl.port";
@@ -1137,6 +1138,14 @@ public class Configuration {
}
/**
+ * Check to see if the Agent should be authenticated via ssl or not
+ * @return false if not, true if ssl needs to be used.
+ */
+ public boolean getAgentSSLAuthentication() {
+ return ("true".equals(properties.getProperty(AGENT_USE_SSL, "true")));
+ }
+
+ /**
* Get the value that should be set for the <code>Strict-Transport-Security</code> HTTP response header for Ambari Server UI.
* <p/>
* By default this will be <code>max-age=31536000; includeSubDomains</code>. For example:
http://git-wip-us.apache.org/repos/asf/ambari/blob/d49cc72e/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index b59ae5d..71e8082 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -335,47 +335,54 @@ public class AmbariServer {
// root.addFilter(new FilterHolder(springSecurityFilter), "/proxy/*", DISPATCHER_TYPES);
}
-
- //Secured connector for 2-way auth
- SslContextFactory contextFactoryTwoWay = new SslContextFactory();
- disableInsecureProtocols(contextFactoryTwoWay);
- SslSelectChannelConnector sslConnectorTwoWay = new
- SslSelectChannelConnector(contextFactoryTwoWay);
- sslConnectorTwoWay.setPort(configs.getTwoWayAuthPort());
-
Map<String, String> configsMap = configs.getConfigsMap();
- String keystore = configsMap.get(Configuration.SRVR_KSTR_DIR_KEY) +
- File.separator + configsMap.get(Configuration.KSTR_NAME_KEY);
- String truststore = configsMap.get(Configuration.SRVR_KSTR_DIR_KEY) +
- File.separator + configsMap.get(Configuration.TSTR_NAME_KEY);
- String srvrCrtPass = configsMap.get(Configuration.SRVR_CRT_PASS_KEY);
- sslConnectorTwoWay.setKeystore(keystore);
- sslConnectorTwoWay.setTruststore(truststore);
- sslConnectorTwoWay.setPassword(srvrCrtPass);
- sslConnectorTwoWay.setKeyPassword(srvrCrtPass);
- sslConnectorTwoWay.setTrustPassword(srvrCrtPass);
- sslConnectorTwoWay.setKeystoreType(configsMap.get(Configuration.KSTR_TYPE_KEY));
- sslConnectorTwoWay.setTruststoreType(configsMap.get(Configuration.TSTR_TYPE_KEY));
- sslConnectorTwoWay.setNeedClientAuth(configs.getTwoWaySsl());
-
- //SSL Context Factory
- SslContextFactory contextFactoryOneWay = new SslContextFactory(true);
- contextFactoryOneWay.setKeyStorePath(keystore);
- contextFactoryOneWay.setTrustStore(truststore);
- contextFactoryOneWay.setKeyStorePassword(srvrCrtPass);
- contextFactoryOneWay.setKeyManagerPassword(srvrCrtPass);
- contextFactoryOneWay.setTrustStorePassword(srvrCrtPass);
- contextFactoryOneWay.setKeyStoreType(configsMap.get(Configuration.KSTR_TYPE_KEY));
- contextFactoryOneWay.setTrustStoreType(configsMap.get(Configuration.TSTR_TYPE_KEY));
- contextFactoryOneWay.setNeedClientAuth(false);
- disableInsecureProtocols(contextFactoryOneWay);
-
- //Secured connector for 1-way auth
- SslSelectChannelConnector sslConnectorOneWay = new SslSelectChannelConnector(contextFactoryOneWay);
- sslConnectorOneWay.setPort(configs.getOneWayAuthPort());
- sslConnectorOneWay.setAcceptors(2);
- sslConnectorTwoWay.setAcceptors(2);
- serverForAgent.setConnectors(new Connector[]{sslConnectorOneWay, sslConnectorTwoWay});
+
+ if (configs.getAgentSSLAuthentication()) {
+ //Secured connector for 2-way auth
+ SslContextFactory contextFactoryTwoWay = new SslContextFactory();
+ disableInsecureProtocols(contextFactoryTwoWay);
+ SslSelectChannelConnector sslConnectorTwoWay = new
+ SslSelectChannelConnector(contextFactoryTwoWay);
+ sslConnectorTwoWay.setPort(configs.getTwoWayAuthPort());
+
+ String keystore = configsMap.get(Configuration.SRVR_KSTR_DIR_KEY) +
+ File.separator + configsMap.get(Configuration.KSTR_NAME_KEY);
+ String truststore = configsMap.get(Configuration.SRVR_KSTR_DIR_KEY) +
+ File.separator + configsMap.get(Configuration.TSTR_NAME_KEY);
+ String srvrCrtPass = configsMap.get(Configuration.SRVR_CRT_PASS_KEY);
+ sslConnectorTwoWay.setKeystore(keystore);
+ sslConnectorTwoWay.setTruststore(truststore);
+ sslConnectorTwoWay.setPassword(srvrCrtPass);
+ sslConnectorTwoWay.setKeyPassword(srvrCrtPass);
+ sslConnectorTwoWay.setTrustPassword(srvrCrtPass);
+ sslConnectorTwoWay.setKeystoreType(configsMap.get(Configuration.KSTR_TYPE_KEY));
+ sslConnectorTwoWay.setTruststoreType(configsMap.get(Configuration.TSTR_TYPE_KEY));
+ sslConnectorTwoWay.setNeedClientAuth(configs.getTwoWaySsl());
+
+ //SSL Context Factory
+ SslContextFactory contextFactoryOneWay = new SslContextFactory(true);
+ contextFactoryOneWay.setKeyStorePath(keystore);
+ contextFactoryOneWay.setTrustStore(truststore);
+ contextFactoryOneWay.setKeyStorePassword(srvrCrtPass);
+ contextFactoryOneWay.setKeyManagerPassword(srvrCrtPass);
+ contextFactoryOneWay.setTrustStorePassword(srvrCrtPass);
+ contextFactoryOneWay.setKeyStoreType(configsMap.get(Configuration.KSTR_TYPE_KEY));
+ contextFactoryOneWay.setTrustStoreType(configsMap.get(Configuration.TSTR_TYPE_KEY));
+ contextFactoryOneWay.setNeedClientAuth(false);
+ disableInsecureProtocols(contextFactoryOneWay);
+
+ //Secured connector for 1-way auth
+ SslSelectChannelConnector sslConnectorOneWay = new SslSelectChannelConnector(contextFactoryOneWay);
+ sslConnectorOneWay.setPort(configs.getOneWayAuthPort());
+ sslConnectorOneWay.setAcceptors(2);
+ sslConnectorTwoWay.setAcceptors(2);
+ serverForAgent.setConnectors(new Connector[]{sslConnectorOneWay, sslConnectorTwoWay});
+ } else {
+ SelectChannelConnector agentConnector = new SelectChannelConnector();
+ agentConnector.setPort(configs.getOneWayAuthPort());
+ agentConnector.setMaxIdleTime(configs.getConnectionMaxIdleTime());
+ serverForAgent.addConnector(agentConnector);
+ }
ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
@@ -713,11 +720,18 @@ public class AmbariServer {
}
/**
+ * Initialize the view registry singleton instance.
+ */
+ public void initViewRegistry() {
+ ViewRegistry.initInstance(this.viewRegistry);
+ }
+
+ /**
* Sets up proxy authentication. This must be done before the server is
* initialized since <code>AmbariMetaInfo</code> requires potential URL
* lookups that may need the proxy.
*/
- static void setupProxyAuth() {
+ public static void setupProxyAuth() {
final String proxyUser = System.getProperty("http.proxyUser");
final String proxyPass = System.getProperty("http.proxyPassword");
http://git-wip-us.apache.org/repos/asf/ambari/blob/d49cc72e/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java
new file mode 100644
index 0000000..ceadbc2
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java
@@ -0,0 +1,120 @@
+/*
+ * 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.ambari.server.functionaltests.server;
+
+import com.google.inject.persist.PersistService;
+import org.apache.ambari.server.controller.AmbariServer;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.configuration.Configuration;
+
+/**
+* Wrap AmbariServer as a testable unit.
+*/
+public class LocalAmbariServer implements Runnable {
+
+ private static Log LOG = LogFactory.getLog(AmbariServer.class);
+
+ /**
+ * Actual ambari server instance.
+ */
+ private AmbariServer ambariServer = null;
+
+ private Injector injector = null;
+
+ private InMemoryDefaultTestModule module = null;
+
+ /**
+ * Default constructor using the default implementation of InMemoryDefaultTestModule.
+ */
+ public LocalAmbariServer() { this.module = new InMemoryDefaultTestModule(); }
+
+ /**
+ * Overloaded constructor for sub-classed InMemoryDefaultTestModule implementations.
+ * @param module
+ */
+ public LocalAmbariServer(InMemoryDefaultTestModule module) { this.module = module; }
+
+ /**
+ * Thread entry point.
+ */
+ @Override
+ public void run(){
+ try {
+ startServer();
+ }
+ catch (Exception ex) {
+ LOG.info("Exception received ", ex);
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Configures the Guice injector to use the in-memory test DB
+ * and attempts to start an instance of AmbariServer.
+ *
+ * @throws Exception
+ */
+ private void startServer() throws Exception {
+ /**
+ * Specify the temp folder as the source for certificate keys.
+ * Without this, the CertificateManager will generate the keys
+ * in the current folder (ambari-server) causing issues with
+ * rat check.
+ */
+ String tmpDir = System.getProperty("java.io.tmpdir");
+ this.module.getProperties().setProperty(Configuration.SRVR_KSTR_DIR_KEY, tmpDir);
+ injector = Guice.createInjector(this.module);
+
+ try {
+ LOG.info("Attempting to start ambari server...");
+
+ AmbariServer.setupProxyAuth();
+ injector.getInstance(GuiceJpaInitializer.class);
+ ambariServer = injector.getInstance(AmbariServer.class);
+ ambariServer.initViewRegistry();
+ ambariServer.run();
+ } catch (InterruptedException ex) {
+ LOG.info(ex);
+ } catch (Throwable t) {
+ LOG.error("Failed to run the Ambari Server", t);
+ stopServer();
+ }
+ }
+
+ /**
+ * Attempts to stop the test AmbariServer instance.
+ * @throws Exception
+ */
+ public void stopServer() throws Exception {
+ LOG.info("Stopping ambari server...");
+
+ if (ambariServer != null) {
+ ambariServer.stop();
+ }
+
+ if (injector != null) {
+ injector.getInstance(PersistService.class).stop();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d49cc72e/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java
new file mode 100644
index 0000000..604ef9e
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.ambari.server.functionaltests.server;
+
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Properties;
+
+import static org.junit.Assert.assertTrue;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
+
+import java.io.StringReader;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonArray;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+
+import org.apache.http.HttpStatus;
+
+/**
+ * Simple test that starts the local ambari server,
+ * tests it's status and shuts down the server.
+ */
+public class StartStopServerTest {
+ /**
+ * Run the ambari server on a thread.
+ */
+ private Thread serverThread = null;
+
+ /**
+ * Instance of the local ambari server, which wraps the actual
+ * ambari server with test configuration.
+ */
+ private LocalAmbariServer server = null;
+
+ /**
+ * Server port
+ */
+ private static int serverPort = 9995;
+
+ /**
+ * Server URL
+ */
+ private static String SERVER_URL_FORMAT = "http://localhost:%d";
+
+ /**
+ * Test URL for GETting the status of the ambari server
+ */
+ private static String stacksPath = "/api/v1/stacks";
+
+ /**
+ * Start our local server on a thread so that it does not block.
+ * @throws Exception
+ */
+ @Before
+ public void setup() throws Exception {
+ InMemoryDefaultTestModule testModule = new InMemoryDefaultTestModule();
+ Properties properties = testModule.getProperties();
+ properties.setProperty(Configuration.AGENT_USE_SSL, "false");
+ properties.setProperty(Configuration.CLIENT_API_PORT_KEY, Integer.toString(serverPort));
+ server = new LocalAmbariServer(testModule);
+ serverThread = new Thread(server);
+ serverThread.start();
+ serverThread.join(20000); // Give a few seconds for the ambari server to start up
+ }
+
+ /**
+ * Shut down our local server.
+ * @throws Exception
+ */
+ @After
+ public void teardown() throws Exception {
+ if (serverThread != null) {
+ serverThread.interrupt();
+ }
+ if (server != null) {
+ server.stopServer();
+ }
+ }
+
+ /**
+ * Waits for the ambari server to startup and then checks it's
+ * status by querying /api/v1/stacks (does not touch the DB)
+ */
+ @Test
+ public void testServerStatus() throws IOException {
+ /**
+ * Query the ambari server for the list of stacks.
+ * A successful GET returns the list of stacks.
+ * We should get a json like:
+ * {
+ * "href" : "http://localhost:9995/api/v1/stacks",
+ * "items" : [
+ * {
+ * "href" : "http://localhost:9995/api/v1/stacks/HDP",
+ * "Stacks" : {
+ * "stack_name" : "HDP"
+ * }
+ * }
+ * ]
+ * }
+ */
+
+ String stacksUrl = String.format(SERVER_URL_FORMAT, serverPort) + stacksPath;
+ HttpClient httpClient = new HttpClient();
+ GetMethod getMethod = new GetMethod(stacksUrl);
+
+ try {
+ int statusCode = httpClient.executeMethod(getMethod);
+
+ assertTrue (statusCode == HttpStatus.SC_OK); // HTTP status code 200
+
+ String responseBody = getMethod.getResponseBodyAsString();
+
+ assertTrue(responseBody != null); // Make sure response body is valid
+
+ JsonElement jsonElement = new JsonParser().parse(new JsonReader(new StringReader(responseBody)));
+
+ assertTrue (jsonElement != null); // Response was a JSON string
+
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+
+ assertTrue (jsonObject.has("items")); // Should have "items" entry
+
+ JsonArray stacksArray = jsonObject.get("items").getAsJsonArray();
+
+ assertTrue (stacksArray.size() > 0); // Should have at least one stack
+
+ } finally {
+ getMethod.releaseConnection();
+ }
+ }
+}