Skip to content

Commit

Permalink
Merge pull request #12 from toast-tk/156-review-webapp-connectivity
Browse files Browse the repository at this point in the history
156 review webapp connectivity
  • Loading branch information
skokaina authored Jun 28, 2017
2 parents a0bdbbc + f08927f commit 0f5ce8e
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 74 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,14 @@ If you'd like to help, [get in touch](https://gitter.im/toast-tk/toast-tk-engine

# Licence
_Toast TK regroups multiple open source projects licensed under the Apache Software License 2._


# How to debug

To run the agent on an IDE with all the right parameters, you have to create a new java application runner :
* Create a new run configuration (Run > Run configuration > New)
* Set the configurations to :
- Project : toast-tk-web-agent
- Main Class : io.vertx.core.Starter
- Program Arguments : run io.toast.tk.agent.web.RestRecorderService
* Save and run with this configuration
4 changes: 2 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
if [ ${TRAVIS_PULL_REQUEST} = 'false' ] && [[ $TRAVIS_BRANCH = 'master' || ${TRAVIS_BRANCH} = 'snapshot' ]]; then
echo 'Checking Quality Gates against sonar'
mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar -Dsonar.host.url=${SONAR_URL} -Dsonar.login=${SONAR_LOGIN} --settings ./settings.xml;
mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar -Dsonar.host.url=${SONAR_URL} -Dsonar.login=${SONAR_LOGIN} -Dsonar.organization=${SONAR_ORGANIZATION} --settings ./settings.xml;
elif [ ${TRAVIS_PULL_REQUEST} != 'false' ]; then
echo 'Build and analyze pull request'
mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar -Dsonar.analysis.mode=issues -Dsonar.host.url=${SONAR_URL} -Dsonar.login=${SONAR_LOGIN} -Dsonar.password=${SONAR_PASSWORD} -Dsonar.github.oauth=${SONAR_GITHUB_OAUTH} -Dsonar.github.repository=toast-tk/toast-tk-agent -Dsonar.github.pullRequest=${TRAVIS_PULL_REQUEST};
mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar -Dsonar.analysis.mode=issues -Dsonar.host.url=${SONAR_URL} -Dsonar.login=${SONAR_LOGIN} -Dsonar.organization=${SONAR_ORGANIZATION} -Dsonar.github.oauth=${SONAR_GITHUB_OAUTH} -Dsonar.github.repository=toast-tk/toast-tk-agent -Dsonar.github.pullRequest=${TRAVIS_PULL_REQUEST};
fi
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,24 @@
public class PluginLoader {

private static final Logger LOG = LoggerFactory.getLogger(PluginLoader.class);
private final String pluginDir;
private final File pluginDir;

public PluginLoader(AgentConfigProvider provider) {
public PluginLoader(AgentConfigProvider provider) throws IllegalAccessException {
this(provider.get().getPluginDir());
}

public PluginLoader(String pluginDir) {
this.pluginDir = pluginDir;
/**
* Build a new plugin loader by passing in the path to the plugin directory
*
* @param pluginDir
* @throws IllegalAccessException
*/
public PluginLoader(String pluginDir) throws IllegalAccessException {
File file = new File(pluginDir);
if(!file.exists() || !file.isDirectory()){
throw new IllegalAccessException("Invalid directory: " + pluginDir);
}
this.pluginDir = file;
}

private static void addSoftwareLibrary(File file,
Expand Down Expand Up @@ -55,9 +65,9 @@ public Module[] collectGuiceModules(List<IAgentPlugin> agentPlugins){
}

private static void extendClassLoaderPath(
final String pluginDir,
final File pluginDir,
ClassLoader classLoader) {
URL[] collectJarsInDirector = collectJarsInDirector(new File(pluginDir));
URL[] collectJarsInDirector = collectJarsInDirector(pluginDir);
for (URL jar : collectJarsInDirector) {
LOG.info("Found plugin jar {}", jar);
try {
Expand All @@ -79,11 +89,15 @@ private static void fillJarsList(
List<URL> jars,
File dir) {
try {
for (File jar : dir.listFiles(pathname -> pathname.isFile() && pathname.getName().endsWith(".jar"))) {
for (File jar : dir.listFiles(PluginLoader::isJar)) {
jars.add(jar.toURI().toURL());
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
LOG.error("Error to find jars in dir:" + dir + " - " + e.getMessage(), e);
}
}

private static boolean isJar(File pathname){
return pathname.getName() != null && pathname.isFile() && pathname.getName().endsWith(".jar");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public void endTest() {
public void initEnvironment() {
//NO-OP
}



@Override
public String getReportsOutputPath(){
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,11 @@ public void initEnvironment() {
public void tearDownEnvironment() {
//NO-OP
}

@Override
public String getReportsOutputPath(){
return null;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,19 @@ public void kill() {
this.fileName = null;
}

public ITestPage run(ITestPage testPage) throws IOException {
/**
* Run a test page
*
* This method will collect the different available adapters
* The adapters are packed in different plugins
* The plugin loader collect the adapters through multiple Guice modules
*
* @param testPage
* @return
* @throws IOException
* @throws IllegalAccessException
*/
public ITestPage run(ITestPage testPage) throws IOException, IllegalAccessException {
LOG.info("Agent plugin class loader: " + IAgentPlugin.class.getClassLoader());
PluginLoader loader = new PluginLoader(provider);
Module[] pluginModules = loader.collectGuiceModules(loader.loadPlugins(IAgentPlugin.class.getClassLoader()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,27 @@
import java.net.UnknownHostException;
import java.util.concurrent.ExecutionException;

import com.google.common.base.Strings;
import io.toast.tk.agent.web.rest.AsyncHttpClientProvider;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.asynchttpclient.ws.WebSocket;
import org.asynchttpclient.ws.WebSocketUpgradeHandler;

import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.inject.Inject;

import io.toast.tk.agent.ui.IAgentApp;
import io.toast.tk.agent.web.rest.AsyncHttpClientProvider;
import io.toast.tk.core.agent.interpret.WebEventRecord;
import io.toast.tk.core.rest.HttpRequest;
import io.toast.tk.core.rest.RestUtils;
import org.asynchttpclient.ws.WebSocket;
import org.asynchttpclient.ws.WebSocketTextListener;
import org.asynchttpclient.ws.WebSocketUpgradeHandler;

public class AgentServerImpl implements IAgentServer {

private static final Logger LOG = LogManager.getLogger(AgentServerImpl.class);
private final AsyncHttpClientProvider wsSlientProvider;
private IAgentApp app;
private WebSocket webSocket;

@Inject
public AgentServerImpl(IAgentApp app, AsyncHttpClientProvider wsSlientProvider){
Expand Down Expand Up @@ -73,35 +72,24 @@ private void openAliveSocket(String apiKey, String localAddress) {
}

private void openAliveSocket(String apiKey) throws InterruptedException, ExecutionException {
final String socketUrl = (app.getConfig().getWebAppUrl() + "/api/agent/stream/"+apiKey)
final String socketUrl = toWsSocketUrl(apiKey);
if(this.webSocket == null || !this.webSocket.isOpen()){
this.webSocket = createSocketAndConnect(socketUrl);
}
}

private WebSocket createSocketAndConnect(final String socketUrl) throws InterruptedException, ExecutionException {
return wsSlientProvider.get().prepareGet(socketUrl)
.execute(new WebSocketUpgradeHandler.Builder()
.addWebSocketListener(new WebAppSocketListener()).build()).get();
}

private String toWsSocketUrl(String apiKey) {
return (app.getConfig().getWebAppUrl()+"/api/agent/stream/"+apiKey)
.replace("https://","wss://")
.replace("http://", "ws://")
.replace("//", "/")
.replace(":/", "://");

wsSlientProvider.get().prepareGet(socketUrl).execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(
new WebSocketTextListener() {
@Override
public void onOpen(WebSocket webSocket) {
//NO-OP
}

@Override
public void onClose(WebSocket webSocket) {
//NO-OP
}

@Override
public void onError(Throwable throwable) {
LOG.error(throwable.getMessage(), throwable);
}

@Override
public void onMessage(String s) {
//NO-OP
}
}
).build()).get();
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.toast.tk.agent.web;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.asynchttpclient.ws.WebSocket;
import org.asynchttpclient.ws.WebSocketTextListener;

/**
* Webapp connection alive checkecker socket
*
*/
public class WebAppSocketListener implements WebSocketTextListener {

private static final Logger LOG = LogManager.getLogger(WebAppSocketListener.class);

@Override
public void onOpen(WebSocket webSocket) {
//NO-OP
}

@Override
public void onClose(WebSocket webSocket) {
//NO-OP
}

@Override
public void onError(Throwable throwable) {
LOG.error(throwable.getMessage(), throwable);
}

@Override
public void onMessage(String message) {
//NO-OP
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,61 @@
package io.toast.tk.agent.web.rest;

import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.Provider;
import io.toast.tk.agent.config.AgentConfig;
import org.asynchttpclient.AsyncHttpClientConfig;
import javax.net.ssl.SSLException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.asynchttpclient.DefaultAsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
import org.asynchttpclient.DefaultAsyncHttpClientConfig.Builder;
import org.asynchttpclient.Realm;
import org.asynchttpclient.Realm.AuthScheme;
import org.asynchttpclient.netty.ssl.InsecureTrustManagerFactory;
import org.asynchttpclient.proxy.ProxyServer;

import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.Provider;

import io.netty.handler.ssl.SslContextBuilder;
import io.toast.tk.agent.config.AgentConfig;

public class AsyncHttpClientProvider implements Provider<DefaultAsyncHttpClient> {

private static final Logger LOG = LogManager.getLogger(AsyncHttpClientProvider.class);
private final AgentConfig config;

@Inject
public AsyncHttpClientProvider(AgentConfig config) {
this.config = config;
}

@Override
public DefaultAsyncHttpClient get() {
if (Boolean.valueOf(this.config.getProxyActivate())) {
String proxyPort = this.config.getProxyPort();
int port = Strings.isNullOrEmpty(proxyPort) ? -1 : Integer.parseInt(proxyPort);
ProxyServer proxyServer = new ProxyServer.Builder(config.getProxyAdress(), port).build();

Builder builder = new DefaultAsyncHttpClientConfig.Builder().setProxyServer(proxyServer);

if (!Strings.isNullOrEmpty(config.getProxyUserName())
&& !Strings.isNullOrEmpty(config.getProxyUserPswd())) {
Realm realm = new Realm.Builder(config.getProxyUserName(), config.getProxyUserPswd())
.setScheme(AuthScheme.BASIC).build();
builder.setRealm(realm);
}

try {
if (proxyServer.getHost().startsWith("https")) {
builder.setSslContext(
SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build());
}
} catch (SSLException e) {
LOG.error(e.getMessage(), e);
}

private final AgentConfig config;

@Inject
public AsyncHttpClientProvider(AgentConfig config){
this.config = config;
}

@Override
public DefaultAsyncHttpClient get() {
if(Boolean.valueOf(this.config.getProxyActivate())){
String proxyPort = this.config.getProxyPort();
int port = Strings.isNullOrEmpty(proxyPort ) ? -1 : Integer.parseInt(proxyPort);
ProxyServer proxyServer = new ProxyServer.Builder(config.getProxyAdress(), port).build();
if(!Strings.isNullOrEmpty(config.getProxyUserName()) && !Strings.isNullOrEmpty(config.getProxyUserPswd()) ){
Realm realm = new Realm.Builder(config.getProxyUserName(), config.getProxyUserPswd()).build();
AsyncHttpClientConfig cf = new DefaultAsyncHttpClientConfig.Builder()
.setProxyServer(proxyServer).setRealm(realm).build();
return new DefaultAsyncHttpClient(cf);
}
AsyncHttpClientConfig cf = new DefaultAsyncHttpClientConfig.Builder()
.setProxyServer(proxyServer).build();
return new DefaultAsyncHttpClient(cf);
}
return new DefaultAsyncHttpClient();
}
return new DefaultAsyncHttpClient(builder.build());
}
return new DefaultAsyncHttpClient();
}
}
3 changes: 3 additions & 0 deletions toast-tk-web-agent/src/main/resources/log4j.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<logger name="org.apache" level="WARN" />
<logger name="httpclient" level="WARN" />

<!-- Console output -->
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.EnhancedPatternLayout">
Expand Down

0 comments on commit 0f5ce8e

Please sign in to comment.