Skip to content

Commit

Permalink
Merge pull request #15 from turing85/feature/router-customizers
Browse files Browse the repository at this point in the history
Allow router customizers
  • Loading branch information
christophd authored Sep 6, 2024
2 parents 891af02 + ce890ee commit 0419f21
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 65 deletions.
47 changes: 28 additions & 19 deletions citrus-remote-sample/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<properties>
<!-- Plugin versions -->
<docker-maven-plugin.version>0.45.0</docker-maven-plugin.version>
<download-maven-plugin.version>1.9.0</download-maven-plugin.version>

<!-- Dependency versions -->
<citrus.version>4.3.1</citrus.version>
Expand All @@ -27,11 +28,12 @@
<citrus.remote.verify.phase>none</citrus.remote.verify.phase>

<docker.build.phase>none</docker.build.phase>
<docker.copy.phase>none</docker.copy.phase>
<docker.remove.phase>none</docker.remove.phase>
<docker.start.phase>none</docker.start.phase>
<docker.stop.phase>none</docker.stop.phase>

<download.wget.phase>none</download.wget.phase>

<failsafe.phase>verify</failsafe.phase>
</properties>

Expand Down Expand Up @@ -96,6 +98,27 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>${download-maven-plugin.version}</version>
<executions>
<execution>
<id>get-citrus-logs</id>
<goals>
<goal>wget</goal>
</goals>
<phase>${download.wget.phase}</phase>
<configuration>
<outputDirectory>${project.build.directory}/container-logs</outputDirectory>
<outputFileName>citrus.log</outputFileName>
<overwrite>true</overwrite>
<skipCache>true</skipCache>
<url>http://localhost:4567/citrus-logs?reset=true</url>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand All @@ -121,14 +144,6 @@
<contextDir>${project.basedir}</contextDir>
<dockerFile>${project.basedir}/src/test/container/Containerfile.temurin</dockerFile>
</build>
<copy>
<entries>
<entry>
<containerPath>/deployment/target/logs/citrus.log</containerPath>
<hostDirectory>${project.build.directory}/container-logs</hostDirectory>
</entry>
</entries>
</copy>
<run>
<autoRemove>true</autoRemove>
<ports>
Expand Down Expand Up @@ -171,13 +186,6 @@
</goals>
<phase>${docker.start.phase}</phase>
</execution>
<execution>
<id>docker-copy-logs</id>
<goals>
<goal>copy</goal>
</goals>
<phase>${docker.copy.phase}</phase>
</execution>
<execution>
<id>stop-container</id>
<goals>
Expand Down Expand Up @@ -312,11 +320,12 @@
<citrus.remote.verify.phase>verify</citrus.remote.verify.phase>

<docker.build.phase>pre-integration-test</docker.build.phase>
<docker.copy.phase>post-integration-test</docker.copy.phase>
<docker.remove.phase>post-integration-test</docker.remove.phase>
<docker.start.phase>pre-integration-test</docker.start.phase>
<docker.stop.phase>post-integration-test</docker.stop.phase>

<download.wget.phase>post-integration-test</download.wget.phase>

<failsafe.phase>none</failsafe.phase>
</properties>
</profile>
Expand All @@ -326,13 +335,13 @@
<citrus.remote.test.phase>none</citrus.remote.test.phase>
<citrus.remote.verify.phase>none</citrus.remote.verify.phase>

<docker.copy.phase>none</docker.copy.phase>
<download.wget.phase>none</download.wget.phase>
</properties>
</profile>
<profile>
<id>skip-docker-build</id>
<properties>
<docker.build.pahse>none</docker.build.pahse>
<docker.build.phase>none</docker.build.phase>
</properties>
</profile>
<profile>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,79 @@
package org.citrusframework.remote.sample.entrypoint;

import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Router;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.RollingFileAppender;
import org.apache.logging.log4j.io.IoBuilder;
import org.citrusframework.remote.CitrusRemoteApplication;
import org.citrusframework.remote.CitrusRemoteServer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;

public class CustomEntrypoint {
private static final Path CITRUS_LOG_PATH = Path.of("target/logs/citrus.log");
public static final RollingFileAppender FILE_ROLLER =
((LoggerContext) LogManager.getContext())
.getConfiguration()
.getAppender("FILE_ROLLER");

public static void main(String... args) {
System.setOut(IoBuilder
.forLogger(LogManager.getLogger("system.out"))
.buildPrintStream());
CitrusRemoteServer.main(args);
CitrusRemoteServer.entrypoint(
args, List.of(CustomEntrypoint::getLogHandler, CustomEntrypoint::rorateLogHandler));
}

private static void getLogHandler(Router router) {
router.get("/citrus-logs")
.handler(CitrusRemoteApplication.wrapThrowingHandler(ctx -> {
HttpServerResponse response = ctx.response();
if (Files.exists(CITRUS_LOG_PATH)) {
response.setStatusCode(HttpStatus.OK.value())
.putHeader(
HttpHeaders.CONTENT_TYPE,
MediaType.TEXT_PLAIN_VALUE)
.putHeader(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"citrus.log\"")
.end(Files.readString(
CITRUS_LOG_PATH,
Charset.defaultCharset()))
.onSuccess(unused -> {
if (Optional.ofNullable(ctx.request().params().get("reset"))
.map(Boolean::parseBoolean)
.orElse(false)) {
rotateCitrusLog();
}
});
} else {
response.setStatusCode(HttpStatus.NOT_FOUND.value()).end();
}
}));
}

private static void rorateLogHandler(Router router) {
router.delete("/citrus-logs")
.handler(CitrusRemoteApplication.wrapThrowingHandler(ctx -> {
HttpServerResponse response = ctx.response();
rotateCitrusLog();
response.setStatusCode(HttpStatus.NO_CONTENT.value())
.end();
}));
}

private static void rotateCitrusLog() {
if (Files.exists(CITRUS_LOG_PATH)) {
FILE_ROLLER.getManager().rollover();
}
}
}
25 changes: 17 additions & 8 deletions citrus-remote-sample/src/test/resources/log4j2.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,29 @@ status = info
property.LOG_DATEFORMAT_PATTERN = yyyy-MM-dd HH:mm:ss.SSS
property.CONSOLE_LOG_PATTERN = %d{${sys:LOG_DATEFORMAT_PATTERN}} %highlight{%5p} --- [%15.15t] %-40.40c{1.} : %msg%n%throwable
property.FILE_LOG_PATTERN = %d{${sys:LOG_DATEFORMAT_PATTERN}} %5p --- [%15.15t] %-40.40c{1.} : %msg%n%throwable
property.LOG_DIR = target/logs
property.LOG_NAME = citrus

appender.console.type = Console
appender.console.layout.pattern = ${sys:CONSOLE_LOG_PATTERN}
appender.console.layout.type = PatternLayout
appender.console.name = STDOUT

appender.file.layout.type = PatternLayout
appender.file.layout.pattern = ${sys:FILE_LOG_PATTERN}
appender.file.fileName = target/logs/citrus.log
appender.file.type = File
appender.file.append = false
appender.file.name = FILE
appender.fileRoller.type = RollingFile
appender.fileRoller.layout.type = PatternLayout
appender.fileRoller.layout.pattern = ${sys:FILE_LOG_PATTERN}
appender.fileRoller.fileName = ${LOG_DIR}/${LOG_NAME}.log
appender.fileRoller.filePattern = ${LOG_DIR}/${LOG_NAME}-%i.log
appender.fileRoller.strategy.type = DefaultRolloverStrategy
appender.fileRoller.strategy.action.type = DELETE
appender.fileRoller.strategy.action.basePath = ${LOG_DIR}
appender.fileRoller.strategy.action.condition.type = IfFileName
appender.fileRoller.strategy.action.condition.regex = citrus-.+\.log
appender.fileRoller.policies.type = Policies
appender.fileRoller.append = false
appender.fileRoller.name = FILE_ROLLER

rootLogger.appenderRef.stdout.ref = STDOUT
rootLogger.appenderRef.file.ref = FILE
rootLogger.appenderRefs = stdout, file
rootLogger.appenderRef.fileRoller.ref = FILE_ROLLER
rootLogger.appenderRefs = stdout, fileRoller
rootLogger.level = info
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Stream;

/**
Expand Down Expand Up @@ -81,23 +82,23 @@ public class CitrusRemoteApplication extends AbstractVerticle {
/** Latest test reports */
private final RemoteTestResultReporter remoteTestResultReporter = new RemoteTestResultReporter();

/** Router customizations */
private final List<Consumer<Router>> routerCustomizations;

private final JsonRequestTransformer requestTransformer = new JsonRequestTransformer();
private final JsonResponseTransformer responseTransformer = new JsonResponseTransformer();

/**
* Default constructor using default configuration.
*/
@SuppressWarnings("unused")
public CitrusRemoteApplication() {
this(new CitrusRemoteConfiguration());
}

/**
* Constructor with given application configuration.
* Constructor with given application configuration and route customizations.
* @param configuration
* @param routerCustomizations
*/
public CitrusRemoteApplication(CitrusRemoteConfiguration configuration) {
public CitrusRemoteApplication(
CitrusRemoteConfiguration configuration,
List<Consumer<Router>> routerCustomizations) {
this.configuration = configuration;
this.routerCustomizations = Optional.ofNullable(routerCustomizations)
.orElse(Collections.emptyList());
}

@Override
Expand All @@ -120,6 +121,7 @@ public void start() {
addResultsEndpoints(router);
addRunEndpoints(router);
addConfigEndpoints(router);
routerCustomizations.forEach(customization -> customization.accept(router));

getVertx().createHttpServer()
.requestHandler(router)
Expand All @@ -139,14 +141,16 @@ private static void addFilesEndpoint(Router router) {
router.get("/files/:name")
.handler(wrapThrowingHandler(ctx -> {
HttpServerResponse response = ctx.response();
response.putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_OCTET_STREAM);
String fileName = ctx.pathParam("name");
Path file = Path.of(fileName);
if (Files.isRegularFile(file)) {
response.putHeader(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + file.getFileName() + "\"")
response.putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_OCTET_STREAM)
.putHeader(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + file.getFileName() + "\"")
.sendFile(fileName);
} else {
response.setStatusCode(HttpResponseStatus.NOT_FOUND.code()).end();
}
}));
}
Expand All @@ -163,11 +167,11 @@ private void addResultsEndpoints(Router router) {
if (remoteResultFuture != null) {
response.putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON);
remoteResultFuture.timeout(timeout, TimeUnit.MILLISECONDS)
.onSuccess(results ->
response.end(responseTransformer.render(results)))
.onFailure(throwable -> response
.setStatusCode(HttpResponseStatus.PARTIAL_CONTENT.code())
.end(responseTransformer.render(Collections.emptyList())));
.onSuccess(results ->
response.end(responseTransformer.render(results)))
.onFailure(throwable -> response
.setStatusCode(HttpResponseStatus.PARTIAL_CONTENT.code())
.end(responseTransformer.render(Collections.emptyList())));
} else {
final List<RemoteResult> results = new ArrayList<>();
remoteTestResultReporter.getLatestResults().doWithResults(result ->
Expand Down Expand Up @@ -291,8 +295,8 @@ private void addConfigEndpoints(Router router) {
CitrusAppConfiguration.class))));
}


private static Handler<RoutingContext> wrapThrowingHandler(ThrowingHandler<RoutingContext> handler) {
public static Handler<RoutingContext> wrapThrowingHandler(
ThrowingHandler<RoutingContext> handler) {
return ctx -> {
try {
handler.handle(ctx);
Expand Down Expand Up @@ -371,8 +375,4 @@ private boolean isPresent(String className) {
return false;
}
}

interface ThrowingHandler<T> {
void handle(T t) throws Exception;
}
}
Loading

0 comments on commit 0419f21

Please sign in to comment.