From 0372289002a3b62577cb476c04fa30322941d515 Mon Sep 17 00:00:00 2001 From: Timon Borter Date: Sun, 18 Aug 2024 18:26:52 +0200 Subject: [PATCH] ci: add sample project props to @maletic and the original sample repository: https://github.com/maletic/citrus-playground. --- citrus-remote-maven-plugin/pom.xml | 4 +- .../AbstractCitrusRemoteAssemblyMojo.java | 19 +- ...rusRemoteAssemblerConfigurationSource.java | 64 ++- pom.xml | 15 +- sample/README.adoc | 98 ++++ sample/citrus/.dockerignore | 2 + sample/citrus/pom.xml | 484 ++++++++++++++++++ sample/citrus/src/test/docker/Dockerfile | 24 + .../plugin/playground/citrus/GetHealthIT.java | 39 ++ .../plugin/playground/citrus/GetHelloIT.java | 47 ++ .../playground/citrus/GetMetricsIT.java | 33 ++ .../configuration/ConfigurationRoot.java | 9 + .../playground/citrus/configuration/Http.java | 38 ++ .../citrus/configuration/Validators.java | 14 + .../resources/citrus-application.properties | 4 + .../src/test/resources/log4j2.properties | 23 + sample/local-deployment/.env | 1 + sample/local-deployment/docker-compose.yml | 33 ++ sample/pom.xml | 26 + sample/service/pom.xml | 157 ++++++ sample/service/src/main/docker/Dockerfile | 26 + .../playground/service/HelloEndpoint.java | 22 + .../playground/service/MyRestClient.java | 15 + .../src/main/resources/application.yml | 7 + 24 files changed, 1167 insertions(+), 37 deletions(-) create mode 100644 sample/README.adoc create mode 100644 sample/citrus/.dockerignore create mode 100644 sample/citrus/pom.xml create mode 100644 sample/citrus/src/test/docker/Dockerfile create mode 100644 sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHealthIT.java create mode 100644 sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHelloIT.java create mode 100644 sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetMetricsIT.java create mode 100644 sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/ConfigurationRoot.java create mode 100644 sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Http.java create mode 100644 sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Validators.java create mode 100644 sample/citrus/src/test/resources/citrus-application.properties create mode 100644 sample/citrus/src/test/resources/log4j2.properties create mode 100644 sample/local-deployment/.env create mode 100644 sample/local-deployment/docker-compose.yml create mode 100644 sample/pom.xml create mode 100644 sample/service/pom.xml create mode 100644 sample/service/src/main/docker/Dockerfile create mode 100644 sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/HelloEndpoint.java create mode 100644 sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/MyRestClient.java create mode 100644 sample/service/src/main/resources/application.yml diff --git a/citrus-remote-maven-plugin/pom.xml b/citrus-remote-maven-plugin/pom.xml index 22c0569..a5f20dc 100644 --- a/citrus-remote-maven-plugin/pom.xml +++ b/citrus-remote-maven-plugin/pom.xml @@ -103,14 +103,14 @@ org.codehaus.plexus plexus-utils provided - 3.1.0 + 4.0.1 org.codehaus.plexus plexus-component-annotations provided - 1.7.1 + 2.2.0 diff --git a/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/AbstractCitrusRemoteAssemblyMojo.java b/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/AbstractCitrusRemoteAssemblyMojo.java index 24a48f9..861be83 100644 --- a/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/AbstractCitrusRemoteAssemblyMojo.java +++ b/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/AbstractCitrusRemoteAssemblyMojo.java @@ -38,6 +38,8 @@ import org.citrusframework.remote.plugin.config.TestJarConfiguration; import java.io.File; +import java.nio.file.attribute.FileTime; +import java.time.Instant; import java.util.List; import java.util.Optional; @@ -105,7 +107,7 @@ protected void createDirs(AssemblyConfiguration assemblyConfig) { } private void initializeAssembly() { - if (!hasAssemblyConfiguration()) { + if (hasNoAssemblyConfiguration()) { assembly = Optional.ofNullable(assembly).orElse(new AssemblyConfiguration()); AssemblyDescriptorConfiguration descriptorConfiguration = new AssemblyDescriptorConfiguration(); descriptorConfiguration.setRef(getDefaultDescriptorRef()); @@ -127,15 +129,14 @@ private void initializeAssembly() { /** * Subclasses provide default descriptor reference. - * @return */ protected abstract String getDefaultDescriptorRef(); - protected boolean hasAssemblyConfiguration() { - return assembly != null && assembly.getDescriptor() != null && - (assembly.getDescriptor().getInline() != null || - assembly.getDescriptor().getFile() != null || - assembly.getDescriptor().getRef() != null); + protected boolean hasNoAssemblyConfiguration() { + return assembly == null || assembly.getDescriptor() == null || + (assembly.getDescriptor().getInline() == null && + assembly.getDescriptor().getFile() == null && + assembly.getDescriptor().getRef() == null); } protected void createAssemblyArchive(AssemblyConfiguration assemblyConfig) throws MojoExecutionException { @@ -144,7 +145,7 @@ protected void createAssemblyArchive(AssemblyConfiguration assemblyConfig) throw try { for (String format : assembly.getFormats()) { - assemblyArchiver.createArchive(assembly, finalName + "-" + assembly.getId(), format, source, false, "merge"); + assemblyArchiver.createArchive(assembly, finalName + "-" + assembly.getId(), format, source, FileTime.from(Instant.now())); } } catch (ArchiveCreationException | AssemblyFormattingException e) { throw new MojoExecutionException("Failed to create assembly for test jar", e); @@ -190,7 +191,7 @@ public void setAssembly(AssemblyConfiguration assembly) { * @return */ public AssemblyConfiguration getAssembly() { - if (!hasAssemblyConfiguration()) { + if (hasNoAssemblyConfiguration()) { initializeAssembly(); } diff --git a/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/assembly/CitrusRemoteAssemblerConfigurationSource.java b/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/assembly/CitrusRemoteAssemblerConfigurationSource.java index 5f0f1ff..fef4c9e 100644 --- a/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/assembly/CitrusRemoteAssemblerConfigurationSource.java +++ b/citrus-remote-maven-plugin/src/main/java/org/citrusframework/remote/plugin/assembly/CitrusRemoteAssemblerConfigurationSource.java @@ -20,6 +20,7 @@ import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugins.assembly.AssemblerConfigurationSource; +import org.apache.maven.plugins.assembly.model.Assembly; import org.apache.maven.plugins.assembly.utils.InterpolationConstants; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.filtering.MavenReaderFilter; @@ -90,6 +91,11 @@ public String[] getDescriptorReferences() { return new String[0]; } + @Override + public List getInlineDescriptors() { + return emptyList(); + } + // ============================================================================================ @Override @@ -112,21 +118,11 @@ public String getFinalName() { return "."; } - @Override - public ArtifactRepository getLocalRepository() { - return mavenSession.getLocalRepository(); - } - @Override public List getReactorProjects() { return reactorProjects; } - @Override - public List getRemoteRepositories() { - return mavenProject.getRemoteArtifactRepositories(); - } - @Override public MavenSession getMavenSession() { return mavenSession; @@ -188,6 +184,36 @@ public FixedStringSearchInterpolator getMainProjectInterpolator() return mainProjectInterpolator; } + @Override + public Integer getOverrideUid() { + return 0; + } + + @Override + public String getOverrideUserName() { + return ""; + } + + @Override + public Integer getOverrideGid() { + return 0; + } + + @Override + public String getOverrideGroupName() { + return mavenProject.getGroupId(); + } + + @Override + public boolean isRecompressZippedFiles() { + return false; + } + + @Override + public String getMergeManifestMode() { + return "merge"; + } + @Override public MavenProject getProject() { return mavenProject; @@ -213,6 +239,11 @@ public List getFilters() { return emptyList(); } + @Override + public Properties getAdditionalProperties() { + return null; + } + @Override public boolean isIncludeProjectBuildFilters() { return true; @@ -263,11 +294,6 @@ public boolean isUpdateOnly() { return false; } - @Override - public boolean isUseJvmChmod() { - return false; - } - @Override public boolean isIgnorePermissions() { return false; @@ -298,13 +324,13 @@ private FixedStringSearchInterpolator createRepositoryInterpolator() final Properties settingsProperties = new Properties(); final MavenSession session = getMavenSession(); - if (getLocalRepository() != null) { - settingsProperties.setProperty("localRepository", getLocalRepository().getBasedir()); - settingsProperties.setProperty("settings.localRepository", getLocalRepository().getBasedir()); + if (mavenSession.getLocalRepository() != null) { + settingsProperties.setProperty("localRepository", mavenSession.getLocalRepository().getBasedir()); + settingsProperties.setProperty("settings.localRepository", mavenSession.getLocalRepository().getBasedir()); } else if (session != null && session.getSettings() != null) { settingsProperties.setProperty("localRepository", session.getSettings().getLocalRepository() ); - settingsProperties.setProperty("settings.localRepository", getLocalRepository().getBasedir() ); + settingsProperties.setProperty("settings.localRepository", mavenSession.getLocalRepository().getBasedir() ); } return FixedStringSearchInterpolator.create(new PropertiesBasedValueSource(settingsProperties)); } diff --git a/pom.xml b/pom.xml index 063410c..a3a34dc 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ 3.0 3.2.0 3.0.0 - 3.1.1 + 3.7.1 2.12.1 3.0.0 3.0.2 @@ -40,7 +40,7 @@ 3.7.1 3.6.2 2.5.3 - 3.0.2 + 3.0.2 1.11.1 3.0.1 2.22.2 @@ -48,12 +48,12 @@ 2.7 0.13 - 4.3.0-SNAPSHOT + 4.3.1 1.1 - 1.2 + 1.3.3 5.3.1 - 2.17.1 - 4.0.4 + 2.17.2 + 6.1.0 2.22.1 2.0.11 2.9.4 @@ -104,6 +104,7 @@ citrus-remote-server citrus-remote-maven-plugin + sample @@ -297,7 +298,7 @@ org.apache.maven.plugins maven-resources-plugin - ${maven.resource.plugin.version} + ${maven.resources.plugin.version} org.apache.maven.plugins diff --git a/sample/README.adoc b/sample/README.adoc new file mode 100644 index 0000000..edc877b --- /dev/null +++ b/sample/README.adoc @@ -0,0 +1,98 @@ +:listing-caption: Listing +:experimental: + += Citrus Playground +:toc: + +== What it is +A small sample project, containing a file:///./service:[`service`] module (representing the system under test) and a file:///./citrus:[`citrus`] module, containing the citrus tests for the service. + +== Prerequisite + +The project uses Java 17, so a Java 17 JDK should be installed. + +The services are deployed with `docker compose`, hence a working docker setup is recommended. For the deploymeht via `docker compose` we need internet connection to load the base image used. + +When deployed, + +* the `service` is exposed under `http://localhost:8080`, and has opened debug port `5006` (also forwarded to `localhost`) +* `citrus` is exposed under `http://localhost:4567`, and has opened debug port `5007` (again, also forwarded to `localhost`). + +Citrus tests are not started automatically, but must be triggered explicitly. + +The citrus tests are written with https://testng.org/doc/:[testng]. + +== Building and deploying the project via `docker-compose` +From the project root, build the project with the profile `build-test-jar` active: + +.Build the project +[source,bash] +---- +$ mvnw -Pbuild-test-jar package +---- + +When the build is completed, start the compose environment: + +.Start docker compose environment +[source, bash] +---- +$ cd local-deployment +$ docker compose up -d +---- + +We verify that both services are running: + +.Verification that both the `service` and `citrus` are running in docker +[source,bash] +---- +$ curl http://localhost:8080/q/health/ready +{ + "status": "UP", + "checks": [ + ] +}% +$ curl http://localhost:4567/health +{ "status": "UP" }% +---- + +== Triggering the tests + +=== From the local machine +We just need to execute the goal `verify` on module `citrus`: + +.Triggering the tests from the local machen +[source,bash] +---- +$ ./mvnw -pl citrus verify +---- + +=== Through remote execution +In this scenario, we trigger the citrus container, running in docker, to execute the tests. + +==== Via `citrus-maven-remote-plugin` +We execute the `verify`goal on module `citrus` with profile `trigger-citrus-remote` activated: + +.Triggering citrus tests via `citrus-maven-remote-plugin` +[source,bash] +---- +$ ./mvnw -Ptrigger-citrus-remote -pl citrus verify +---- + +==== Via `cURL` +We execute the following `curl` command to trigger the tests without the `citrus-maven-remote-plugin`: + +.Triggering citrus tests via `cURL` +[source,bash] +---- +$ curl -H 'Content-Type: application/json' -d '{ "engine": "testng" }' -X PUT -v http://localhost:4567/run +---- + +== Cleanup +To clean up, we shutdown the docker containers: + +.Shutting down the containers +[source,bash] +---- +$ cd local-deployment +$ docker compose down +---- \ No newline at end of file diff --git a/sample/citrus/.dockerignore b/sample/citrus/.dockerignore new file mode 100644 index 0000000..55ecd56 --- /dev/null +++ b/sample/citrus/.dockerignore @@ -0,0 +1,2 @@ +target/*.jar +!target/*-citrus-tests.jar \ No newline at end of file diff --git a/sample/citrus/pom.xml b/sample/citrus/pom.xml new file mode 100644 index 0000000..b538ded --- /dev/null +++ b/sample/citrus/pom.xml @@ -0,0 +1,484 @@ + + + 4.0.0 + + + citrus-remote-samples + org.citrusframework + 4.3.0-SNAPSHOT + ../pom.xml + + + citrus-playground-citrus + Citrus Playground :: Citrus + + + + 3.0.0 + + + ${project.version} + 6.1.12 + + + http://localhost:4567 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.version} + + + org.citrusframework + citrus-remote-maven-plugin + ${citrus.remote.version} + + + org.apache.maven.plugins + maven-resources-plugin + ${maven.resources.plugin.version} + + + org.apache.maven.plugins + maven-jar-plugin + ${maven.jar.plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-surefire-plugin.version} + + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + default-resources + none + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + default-compile + none + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + default-jar + none + + + + + + org.citrusframework + citrus-remote-maven-plugin + + + build-uber-jar + + test-jar + + + + + + citrus-tests + + jar + + false + + + / + false + true + true + test + + + + + + metaInf-spring + + + + + + + package + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + default-test + none + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack-quarkus-app + pre-integration-test + + unpack + + + + + org.citrusframework + citrus-playground-service + ${project.version} + jar + ${project.build.directory} + quarkus-app/** + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.4.1 + + + start-quarkus + pre-integration-test + + exec + + + java + + -jar + ${project.build.directory}/quarkus-app/quarkus-run.jar + + true + true + + + + + + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + start-playground-service + pre-integration-test + + + integration-tests + + integration-test + verify + + + + + + + + + + + org.citrusframework + citrus-bom + ${citrus.version} + pom + import + + + org.citrusframework + citrus-remote-server + ${citrus.remote.version} + + + + + + + + org.springframework + spring-test + ${spring.version} + + + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j2.version} + + + + + org.citrusframework + citrus-base + + + org.citrusframework + citrus-spring + + + org.citrusframework + citrus-endpoint-catalog + + + org.citrusframework + citrus-testng + + + org.citrusframework + citrus-http + + + org.citrusframework + citrus-validation-json + + + org.citrusframework + citrus-validation-text + + + org.citrusframework + citrus-remote-server + + + + + org.citrusframework + citrus-playground-service + ${project.version} + test + + + + + + trigger-citrus-remote + + + + org.apache.maven.plugins + maven-resources-plugin + + + default-testResources + none + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + default-testCompile + none + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + default-test + none + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + integration-tests + none + + + + + + org.citrusframework + citrus-remote-maven-plugin + + + build-uber-jar + none + + + trigger-citrus-remote + + test + verify + + verify + + + ${citrus.remote.server.url} + + + testng + true + 15000 + + + citrus-remote + + + + + + + + + + + linux + + + unix + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.4.1 + + + wait-for-port + pre-integration-test + + exec + + + bash + + -c + + for i in {1..30}; do + if nc -z localhost 8080; then + echo "Port is available" + exit 0 + fi + echo "Waiting for port..." + sleep 1 + done + echo "Port not available after 30 seconds" + exit 1 + + + + + + + + + + + + windows + + + windows + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.4.1 + + + wait-for-port + pre-integration-test + + exec + + + powershell + + + for ($i = 1; $i -le 30; $i++) { + $test = Test-NetConnection -ComputerName localhost -Port 8080 -WarningAction SilentlyContinue + if ($test.TcpTestSucceeded) { + Write-Host "Port is available" + exit 0 + } + Write-Host "Waiting for port..." + Start-Sleep -Seconds 1 + } + Write-Host "Port not available after 30 seconds" + exit 1 + + + + + + + + + + + \ No newline at end of file diff --git a/sample/citrus/src/test/docker/Dockerfile b/sample/citrus/src/test/docker/Dockerfile new file mode 100644 index 0000000..f97d331 --- /dev/null +++ b/sample/citrus/src/test/docker/Dockerfile @@ -0,0 +1,24 @@ +# Java 17 +FROM docker.io/library/eclipse-temurin:17.0.6_10-jre-alpine +ARG JAR=target/*-citrus-tests.jar +ARG DEPLOYMENT_DIR=/deployment +ENV LANG="en_US.UTF-8" LANGUAGE="en_US:en" + +USER root +RUN adduser \ + -u 185 \ + -h ${DEPLOYMENT_DIR} \ + -s /bin/sh \ + -D \ + runner + +WORKDIR ${DEPLOYMENT_DIR} +COPY --chmod=755 ${JAR} ${DEPLOYMENT_DIR}/app.jar + +USER 185:185 +ENTRYPOINT [ \ + "java", \ + "-jar", \ + "app.jar" \ +] + diff --git a/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHealthIT.java b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHealthIT.java new file mode 100644 index 0000000..faf4b3e --- /dev/null +++ b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHealthIT.java @@ -0,0 +1,39 @@ +package org.citrusframework.remote.plugin.playground.citrus; + +import org.citrusframework.TestCaseRunner; +import org.citrusframework.annotations.CitrusResource; +import org.citrusframework.annotations.CitrusTest; +import org.citrusframework.message.MessageType; +import org.citrusframework.testng.spring.TestNGCitrusSpringSupport; +import org.citrusframework.remote.plugin.playground.citrus.configuration.Http; +import org.springframework.http.HttpStatus; +import org.testng.annotations.Optional; +import org.testng.annotations.Test; + +import static org.citrusframework.http.actions.HttpActionBuilder.http; +import static org.citrusframework.validation.json.JsonPathMessageValidationContext.Builder.jsonPath; + +@SuppressWarnings("unused") +public class GetHealthIT extends TestNGCitrusSpringSupport { + @Test + @CitrusTest + public void getHealth(@Optional @CitrusResource TestCaseRunner runner) { + // WHEN + // @formatter:off + runner.$(http() + .client(Http.SERVICE_CLIENT_NAME) + .send() + .get("/q/health")); + + // THEN + runner.$(http() + .client(Http.SERVICE_CLIENT_NAME) + .receive() + .response(HttpStatus.OK) + .message() + .type(MessageType.JSON) + .validate(jsonPath() + .expression("$.status", "UP"))); + // @formatter:on + } +} diff --git a/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHelloIT.java b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHelloIT.java new file mode 100644 index 0000000..562c7cd --- /dev/null +++ b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetHelloIT.java @@ -0,0 +1,47 @@ +package org.citrusframework.remote.plugin.playground.citrus; + +import org.citrusframework.TestCaseRunner; +import org.citrusframework.annotations.CitrusResource; +import org.citrusframework.annotations.CitrusTest; +import org.citrusframework.message.MessageType; +import org.citrusframework.testng.spring.TestNGCitrusSpringSupport; +import org.citrusframework.remote.plugin.playground.citrus.configuration.Http; +import org.springframework.http.HttpStatus; +import org.testng.annotations.Optional; +import org.testng.annotations.Test; + +import static org.citrusframework.container.Async.Builder.async; +import static org.citrusframework.http.actions.HttpActionBuilder.http; + +@SuppressWarnings("unused") +public class GetHelloIT extends TestNGCitrusSpringSupport { + @Test + @CitrusTest + public void getHello(@Optional @CitrusResource TestCaseRunner runner) { + // GIVEN + // @formatter:off + runner.$(async().actions( + http().server(Http.HTTP_SERVER_NAME) + .receive().get("/greeting"), + http().server(Http.HTTP_SERVER_NAME) + .send() + .response(HttpStatus.OK) + .message().body("Hai"))); + + // WHEN + runner.$(http() + .client(Http.SERVICE_CLIENT_NAME) + .send() + .get("/hello")); + + // THEN + runner.$(http() + .client(Http.SERVICE_CLIENT_NAME) + .receive() + .response(HttpStatus.OK) + .message() + .type(MessageType.PLAINTEXT) + .body("Hai")); + // @formatter:on + } +} diff --git a/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetMetricsIT.java b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetMetricsIT.java new file mode 100644 index 0000000..c133391 --- /dev/null +++ b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/GetMetricsIT.java @@ -0,0 +1,33 @@ +package org.citrusframework.remote.plugin.playground.citrus; + +import org.citrusframework.TestCaseRunner; +import org.citrusframework.annotations.CitrusResource; +import org.citrusframework.annotations.CitrusTest; +import org.citrusframework.testng.spring.TestNGCitrusSpringSupport; +import org.citrusframework.remote.plugin.playground.citrus.configuration.Http; +import org.springframework.http.HttpStatus; +import org.testng.annotations.Optional; +import org.testng.annotations.Test; + +import static org.citrusframework.http.actions.HttpActionBuilder.http; + +@SuppressWarnings("unused") +public class GetMetricsIT extends TestNGCitrusSpringSupport { + @Test + @CitrusTest + public void getMetrics(@Optional @CitrusResource TestCaseRunner runner) { + // WHEN + // @formatter:off + runner.$(http() + .client(Http.SERVICE_CLIENT_NAME) + .send() + .get("/q/metrics")); + + // THEN + runner.$(http() + .client(Http.SERVICE_CLIENT_NAME) + .receive() + .response(HttpStatus.OK)); + // @formatter:on + } +} diff --git a/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/ConfigurationRoot.java b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/ConfigurationRoot.java new file mode 100644 index 0000000..a88b44d --- /dev/null +++ b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/ConfigurationRoot.java @@ -0,0 +1,9 @@ +package org.citrusframework.remote.plugin.playground.citrus.configuration; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import({ Http.class, Validators.class }) +public class ConfigurationRoot { +} diff --git a/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Http.java b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Http.java new file mode 100644 index 0000000..b5654c8 --- /dev/null +++ b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Http.java @@ -0,0 +1,38 @@ +package org.citrusframework.remote.plugin.playground.citrus.configuration; + +import org.citrusframework.dsl.endpoint.CitrusEndpoints; +import org.citrusframework.http.client.HttpClient; +import org.citrusframework.http.server.HttpServer; +import org.citrusframework.http.server.HttpServerBuilder; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.Duration; + +@Configuration +public class Http { + + public static final String SERVICE_CLIENT_NAME = "serviceClient"; + public static final String HTTP_SERVER_NAME = "httpServer"; + + @Bean + @Qualifier(SERVICE_CLIENT_NAME) + public HttpClient serviceClient(@Value("${test-config.sut.url}") String sutUrl) { + return CitrusEndpoints + .http().client() + .requestUrl(sutUrl) + .build(); + } + + @Bean + @Qualifier(HTTP_SERVER_NAME) + public HttpServer httpServer(@Value("${test-config.http.server.port}") int port) { + return new HttpServerBuilder() + .port(port) + .timeout(Duration.ofSeconds(10).toMillis()) + .autoStart(true) + .build(); + } +} diff --git a/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Validators.java b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Validators.java new file mode 100644 index 0000000..10bd647 --- /dev/null +++ b/sample/citrus/src/test/java/org/citrusframework/remote/plugin/playground/citrus/configuration/Validators.java @@ -0,0 +1,14 @@ +package org.citrusframework.remote.plugin.playground.citrus.configuration; + +import org.citrusframework.validation.text.PlainTextMessageValidator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Validators { + + @Bean + PlainTextMessageValidator defaultPlainTextMessageValidator() { + return new PlainTextMessageValidator(); + } +} diff --git a/sample/citrus/src/test/resources/citrus-application.properties b/sample/citrus/src/test/resources/citrus-application.properties new file mode 100644 index 0000000..66378a1 --- /dev/null +++ b/sample/citrus/src/test/resources/citrus-application.properties @@ -0,0 +1,4 @@ +citrus.spring.java.config=org.citrusframework.remote.plugin.playground.citrus.configuration.ConfigurationRoot + +test-config.http.server.port=${HTTP_SERVER_PORT:8081} +test-config.sut.url=${SUT_URL:http://localhost:8080} \ No newline at end of file diff --git a/sample/citrus/src/test/resources/log4j2.properties b/sample/citrus/src/test/resources/log4j2.properties new file mode 100644 index 0000000..962cd06 --- /dev/null +++ b/sample/citrus/src/test/resources/log4j2.properties @@ -0,0 +1,23 @@ +name=Log4j2PropertiesConfig +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 + +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 + +rootLogger.appenderRef.stdout.ref=STDOUT +rootLogger.appenderRef.file.ref=FILE +rootLogger.appenderRefs=stdout, file +rootLogger.level=info \ No newline at end of file diff --git a/sample/local-deployment/.env b/sample/local-deployment/.env new file mode 100644 index 0000000..4b1406d --- /dev/null +++ b/sample/local-deployment/.env @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME=citrus-playground \ No newline at end of file diff --git a/sample/local-deployment/docker-compose.yml b/sample/local-deployment/docker-compose.yml new file mode 100644 index 0000000..03198aa --- /dev/null +++ b/sample/local-deployment/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3.8' +services: + service: + container_name: service + image: citrus-playground/service + build: + context: ../service + dockerfile: ../service/src/main/docker/Dockerfile + environment: + JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 + QUARKUS_LAUNCH_DEVMODE: true + QUARKUS_REST_CLIENT__EXTERNAL__URL: http://citrus-tests:8080 + ports: + - '8080:8080' + - '5006:5005' + citrus-tests: + container_name: citrus-tests + image: citrus-playground/citrus-tests + build: + context: ../citrus + dockerfile: ../citrus/src/test/docker/Dockerfile + command: + - '--skipTests' + - 'true' + - '--duration' + - '9223372036854775807' + environment: + HTTP_SERVER_PORT: 8080 + JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 + SUT_URL: http://service:8080 + ports: + - '4567:4567' + - '5007:5005' \ No newline at end of file diff --git a/sample/pom.xml b/sample/pom.xml new file mode 100644 index 0000000..5a24a9d --- /dev/null +++ b/sample/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + + citrus-remote + org.citrusframework + 4.3.0-SNAPSHOT + ../pom.xml + + + citrus-remote-samples + pom + Citrus Playground :: Sample + + + true + + + + service + citrus + + diff --git a/sample/service/pom.xml b/sample/service/pom.xml new file mode 100644 index 0000000..e056ea1 --- /dev/null +++ b/sample/service/pom.xml @@ -0,0 +1,157 @@ + + + 4.0.0 + + citrus-remote-samples + org.citrusframework + 4.3.0-SNAPSHOT + ../pom.xml + + + citrus-playground-service + Citrus Playground :: Service + + + + 3.0.0 + quarkus-bom + io.quarkus + 3.1.0.Final + http://localhost:8080 + mutable-jar + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + + + + + + + maven-compiler-plugin + ${maven.compiler.version} + + + -parameters + + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven.jar.plugin.version} + + ${project.build.directory} + + classes/** + quarkus-app/** + + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + + + + + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + + io.quarkus + quarkus-config-yaml + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-rest-client + + + io.quarkus + quarkus-rest-client-jackson + + + io.quarkus + quarkus-micrometer + + + io.quarkus + quarkus-micrometer-registry-prometheus + + + io.quarkus + quarkus-smallrye-health + + + + + + native + + + native + + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + + + + + + + + + native + + + + \ No newline at end of file diff --git a/sample/service/src/main/docker/Dockerfile b/sample/service/src/main/docker/Dockerfile new file mode 100644 index 0000000..926323f --- /dev/null +++ b/sample/service/src/main/docker/Dockerfile @@ -0,0 +1,26 @@ +# Java 17 +FROM docker.io/library/eclipse-temurin:17.0.6_10-jre-alpine +ARG JAR=target/*-citrus-tests.jar +ARG DEPLOYMENT_DIR=/deployment +ENV LANG="en_US.UTF-8" LANGUAGE="en_US:en" + +USER root +RUN adduser \ + -u 185 \ + -h ${DEPLOYMENT_DIR} \ + -s /bin/sh \ + -D \ + runner + +WORKDIR ${DEPLOYMENT_DIR} +COPY --chmod=775 target/quarkus-app/lib/ ${DEPLOYMENT_DIR}/lib/ +COPY --chmod=775 target/quarkus-app/*.jar ${DEPLOYMENT_DIR}/ +COPY --chmod=775 target/quarkus-app/app/ ${DEPLOYMENT_DIR}/app/ +COPY --chmod=775 target/quarkus-app/quarkus/ ${DEPLOYMENT_DIR}/quarkus/ + +USER 185:185 +ENTRYPOINT [ \ + "java", \ + "-jar", \ + "quarkus-run.jar" \ +] \ No newline at end of file diff --git a/sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/HelloEndpoint.java b/sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/HelloEndpoint.java new file mode 100644 index 0000000..6358608 --- /dev/null +++ b/sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/HelloEndpoint.java @@ -0,0 +1,22 @@ +package org.citrusframework.remote.plugin.playground.service; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("hello") +@Produces(MediaType.TEXT_PLAIN) +public class HelloEndpoint { + private final MyRestClient myRestClient; + + public HelloEndpoint(@RestClient MyRestClient myRestClient) { + this.myRestClient = myRestClient; + } + + @GET + public String hello() { + return myRestClient.getGreeting(); + } +} diff --git a/sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/MyRestClient.java b/sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/MyRestClient.java new file mode 100644 index 0000000..fa5389d --- /dev/null +++ b/sample/service/src/main/java/org/citrusframework/remote/plugin/playground/service/MyRestClient.java @@ -0,0 +1,15 @@ +package org.citrusframework.remote.plugin.playground.service; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@Path("/greeting") +@Produces(MediaType.TEXT_PLAIN) +@RegisterRestClient(configKey = "external") +public interface MyRestClient { + @GET + String getGreeting(); +} diff --git a/sample/service/src/main/resources/application.yml b/sample/service/src/main/resources/application.yml new file mode 100644 index 0000000..fab9c96 --- /dev/null +++ b/sample/service/src/main/resources/application.yml @@ -0,0 +1,7 @@ +quarkus: + live-reload: + password: changeMe + rest-client: + external: + url: ${QUARKUS_REST_CLIENT__EXTERNAL__URL:http://localhost:8081} + scope: jakarta.inject.Singleton \ No newline at end of file