From dc57412669cb76bc088c3418b6c560c552f24889 Mon Sep 17 00:00:00 2001 From: Pablo Gonzalez Granados Date: Wed, 28 Sep 2022 20:48:40 +0200 Subject: [PATCH] Add Helm coverage - base usecase (#835) --- .github/workflows/ci.yml | 2 +- README.md | 7 ++ helm/helm-minimum/pom.xml | 103 ++++++++++++++++++ .../src/main/docker/Dockerfile.jvm | 94 ++++++++++++++++ .../ts/helm/minimum/CustomReadiness.java | 16 +++ .../ts/helm/minimum/GreetingResource.java | 15 +++ .../src/main/resources/application.properties | 14 +++ .../minimum/OpenShiftHelmSimpleAppIT.java | 100 +++++++++++++++++ .../src/test/resources/application.properties | 9 ++ .../src/test/resources/test.properties | 4 + pom.xml | 7 ++ 11 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 helm/helm-minimum/pom.xml create mode 100644 helm/helm-minimum/src/main/docker/Dockerfile.jvm create mode 100644 helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/CustomReadiness.java create mode 100644 helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/GreetingResource.java create mode 100644 helm/helm-minimum/src/main/resources/application.properties create mode 100644 helm/helm-minimum/src/test/java/io/quarkus/ts/helm/minimum/OpenShiftHelmSimpleAppIT.java create mode 100644 helm/helm-minimum/src/test/resources/application.properties create mode 100644 helm/helm-minimum/src/test/resources/test.properties diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fcb1e54f9..01e81f5a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: run: tar -xzf maven-repo.tgz -C ~ - name: Build with Maven run: | - mvn -V -B -s .github/mvn-settings.xml verify -Dall-modules -Dvalidate-format -DskipTests -DskipITs + mvn -V -B -s .github/mvn-settings.xml verify -Dall-modules -Dvalidate-format -DskipTests -DskipITs -Dquarkus.container-image.build=false -Dquarkus.container-image.push=false detect-test-suite-modules: name: Detect Modules in PR runs-on: ubuntu-latest diff --git a/README.md b/README.md index ac579043d..2d69e58e2 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,13 @@ This module covers some basic scenarios around GraphQL. ### `http/graphql-telemetry` This module covers some basic scenarios around OpenTelemetry usage with GraphQL. +### `helm/helm-minimum` +This module covers Helm integration by Quarkus-helm extension`io.quarkiverse.helm:quarkus-helm` +The above extension will generate a Helm chart based on your `application.properties`. We have set up +a HelloWorld application and then deploy it into Openshift through Helm. + +*Note:* This module will push a docker image into `quay.io/quarkusqeteam/ts-quarkus-helm-simple-app` repository, you will need to be logged into Quay in order to push the image. + ### `javaee-like-getting-started` Based on `mvn io.quarkus:quarkus-maven-plugin:999-SNAPSHOT:create -DprojectGroupId=io.quarkus.qe -DprojectArtifactId=scenario-101-getting-started -DprojectVersion=1.0.0-SNAPSHOT -DclassName="io.quarkus.qe.hello.GreetingResource" -Dextensions=io.quarkus:quarkus-hibernate-orm,io.quarkus:quarkus-jsonb,io.quarkus:quarkus-jsonp,io.quarkus:quarkus-resteasy-jsonb,io.quarkus:quarkus-narayana-jta,io.quarkus:quarkus-elytron-security,io.quarkus:quarkus-scheduler,io.quarkus:quarkus-swagger-ui,io.quarkus:quarkus-hibernate-validator,io.quarkus:quarkus-undertow-websockets,io.quarkus:quarkus-smallrye-fault-tolerance,io.quarkus:quarkus-smallrye-metrics,io.quarkus:quarkus-smallrye-openapi,io.quarkus:quarkus-smallrye-jwt,io.quarkus:quarkus-smallrye-health,io.quarkus:quarkus-smallrye-opentracing` generated project diff --git a/helm/helm-minimum/pom.xml b/helm/helm-minimum/pom.xml new file mode 100644 index 000000000..29f0e074d --- /dev/null +++ b/helm/helm-minimum/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + + io.quarkus.ts.qe + parent + 1.0.0-SNAPSHOT + ../.. + + helm-minimum + jar + Quarkus QE TS: Helm minimum + + + io.quarkus + quarkus-openshift + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-container-image-docker + + + io.quarkiverse.helm + quarkus-helm + + + io.quarkus + quarkus-smallrye-health + + + io.quarkus.qe + quarkus-test-helm + test + + + io.quarkus.qe + quarkus-test-openshift + test + + + io.quarkus.qe + quarkus-test-core + test + + + + + + openshift + + + openshift + + + + **/OpenShift*IT.java + no + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + + + + + + true + true + + + + + + + + + + native + + + native + + + + true + + + + diff --git a/helm/helm-minimum/src/main/docker/Dockerfile.jvm b/helm/helm-minimum/src/main/docker/Dockerfile.jvm new file mode 100644 index 000000000..484d004ab --- /dev/null +++ b/helm/helm-minimum/src/main/docker/Dockerfile.jvm @@ -0,0 +1,94 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the container image run: +# +# ./mvnw package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/helm-quickstart-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/helm-quickstart-jvm +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005 +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 quarkus/helm-quickstart-jvm +# +# This image uses the `run-java.sh` script to run the application. +# This scripts computes the command line to execute your Java application, and +# includes memory/GC tuning. +# You can configure the behavior using the following environment properties: +# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") +# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options +# in JAVA_OPTS (example: "-Dsome.property=foo") +# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is +# used to calculate a default maximal heap memory based on a containers restriction. +# If used in a container without any memory constraints for the container then this +# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio +# of the container available memory as set here. The default is `50` which means 50% +# of the available memory is used as an upper boundary. You can skip this mechanism by +# setting this value to `0` in which case no `-Xmx` option is added. +# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This +# is used to calculate a default initial heap memory based on the maximum heap memory. +# If used in a container without any memory constraints for the container then this +# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio +# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` +# is used as the initial heap size. You can skip this mechanism by setting this value +# to `0` in which case no `-Xms` option is added (example: "25") +# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. +# This is used to calculate the maximum value of the initial heap memory. If used in +# a container without any memory constraints for the container then this option has +# no effect. If there is a memory constraint then `-Xms` is limited to the value set +# here. The default is 4096MB which means the calculated value of `-Xms` never will +# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") +# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output +# when things are happening. This option, if set to true, will set +# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). +# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: +# true"). +# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). +# - CONTAINER_CORE_LIMIT: A calculated core limit as described in +# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") +# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). +# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. +# (example: "20") +# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. +# (example: "40") +# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. +# (example: "4") +# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus +# previous GC times. (example: "90") +# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") +# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") +# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should +# contain the necessary JRE command-line options to specify the required GC, which +# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). +# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") +# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") +# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be +# accessed directly. (example: "foo.example.com,bar.example.com") +# +### +FROM registry.access.redhat.com/ubi8/openjdk-11:1.11 + +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' + + +# We make four distinct layers so if there are application changes the library layers can be re-used +COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=185 target/quarkus-app/*.jar /deployments/ +COPY --chown=185 target/quarkus-app/app/ /deployments/app/ +COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 185 +ENV AB_JOLOKIA_OFF="" +ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" + diff --git a/helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/CustomReadiness.java b/helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/CustomReadiness.java new file mode 100644 index 000000000..b32886934 --- /dev/null +++ b/helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/CustomReadiness.java @@ -0,0 +1,16 @@ +package io.quarkus.ts.helm.minimum; + +import javax.enterprise.context.ApplicationScoped; + +import org.eclipse.microprofile.health.HealthCheck; +import org.eclipse.microprofile.health.HealthCheckResponse; +import org.eclipse.microprofile.health.Readiness; + +@Readiness +@ApplicationScoped +public class CustomReadiness implements HealthCheck { + @Override + public HealthCheckResponse call() { + return HealthCheckResponse.up("Hello custom Helm Readiness!"); + } +} diff --git a/helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/GreetingResource.java b/helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/GreetingResource.java new file mode 100644 index 000000000..4f6877d38 --- /dev/null +++ b/helm/helm-minimum/src/main/java/io/quarkus/ts/helm/minimum/GreetingResource.java @@ -0,0 +1,15 @@ +package io.quarkus.ts.helm.minimum; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/greeting") +public class GreetingResource { + @GET + @Produces(MediaType.TEXT_PLAIN) + public String sayHello() { + return "Hello Helm!"; + } +} diff --git a/helm/helm-minimum/src/main/resources/application.properties b/helm/helm-minimum/src/main/resources/application.properties new file mode 100644 index 000000000..6484796be --- /dev/null +++ b/helm/helm-minimum/src/main/resources/application.properties @@ -0,0 +1,14 @@ +# Application properties +quarkus.openshift.route.expose=true +// TODO https://github.com/quarkiverse/quarkus-helm/issues/100 +#quarkus.container-image.image=quay.io/quarkusqeteam/ts-quarkus-helm-simple-app:latest +quarkus.helm.name=my-chart +quarkus.container-image.builder=docker + +quarkus.container-image.registry=quay.io +quarkus.container-image.group=quarkusqeteam +quarkus.container-image.name=minimum-quarkus-helm +quarkus.container-image.tag=v1 + + + diff --git a/helm/helm-minimum/src/test/java/io/quarkus/ts/helm/minimum/OpenShiftHelmSimpleAppIT.java b/helm/helm-minimum/src/test/java/io/quarkus/ts/helm/minimum/OpenShiftHelmSimpleAppIT.java new file mode 100644 index 000000000..326c998e5 --- /dev/null +++ b/helm/helm-minimum/src/test/java/io/quarkus/ts/helm/minimum/OpenShiftHelmSimpleAppIT.java @@ -0,0 +1,100 @@ +package io.quarkus.ts.helm.minimum; + +import static org.awaitility.Awaitility.await; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItemInArray; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import javax.inject.Inject; + +import org.apache.http.HttpStatus; +import org.jboss.logging.Logger; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.bootstrap.QuarkusHelmClient; +import io.quarkus.test.bootstrap.inject.OpenShiftClient; +import io.quarkus.test.scenarios.OpenShiftScenario; +import io.quarkus.test.scenarios.annotations.DisabledOnNative; +import io.restassured.RestAssured; + +@OpenShiftScenario +// Helm is concerned just about image name, Native compilation is not relevant +@DisabledOnNative +public class OpenShiftHelmSimpleAppIT { + + private static final Logger LOG = Logger.getLogger(OpenShiftHelmSimpleAppIT.class); + + private static final String PLATFORM_OPENSHIFT = "openshift"; + private static final String CHART_NAME = "my-chart"; + private static final String APP_SERVICE_NAME = "minimum-quarkus-helm"; + private static final int TIMEOUT_MIN = 5; + private static String APP_URL; + + @Inject + static QuarkusHelmClient helmClient; + + @Inject + static OpenShiftClient ocpClient; + + @BeforeAll + public static void tearUp() { + installChart(CHART_NAME); + } + + @AfterAll + public static void tearDown() { + helmClient.uninstallChart(CHART_NAME); + } + + @Test + public void deployHelmQuarkusApplication() { + assertThat(getAvailableChartNames().toArray(), hasItemInArray(CHART_NAME)); + RestAssured.given().baseUri(APP_URL).get("/greeting") + .then().statusCode(HttpStatus.SC_OK) + .body(is("Hello Helm!")); + } + + @Test + public void customReadiness() { + RestAssured.given().baseUri(APP_URL).get("/q/health/ready") + .then().statusCode(HttpStatus.SC_OK) + .body("checks[0].name", is("Hello custom Helm Readiness!")); + } + + private List getAvailableChartNames() { + List charts = helmClient.getCharts(); + assertTrue(charts.size() > 0, "Chart " + CHART_NAME + " not found. Installation fail"); + return charts.stream() + .map(QuarkusHelmClient.ChartListResult::getName) + .map(String::trim) + .collect(Collectors.toList()); + } + + private static void installChart(String chartName) { + String chartFolderName = helmClient.getWorkingDirectory().getAbsolutePath() + "/helm/" + PLATFORM_OPENSHIFT + "/" + + chartName; + helmClient.run("dependency", "update", chartFolderName); + QuarkusHelmClient.Result chartResultCmd = helmClient.installChart(chartName, chartFolderName); + thenSucceed(chartResultCmd); + + APP_URL = ocpClient.url(APP_SERVICE_NAME).getRestAssuredStyleUri(); + LOG.info("Endpoint URL: " + APP_URL); + + await().ignoreExceptions().atMost(TIMEOUT_MIN, TimeUnit.MINUTES) + .untilAsserted(() -> RestAssured.given().baseUri(APP_URL).get("/q/health/live") + .then().statusCode(HttpStatus.SC_OK)); + } + + private static void thenSucceed(QuarkusHelmClient.Result chartResultCmd) { + assertTrue( + chartResultCmd.isSuccessful(), + String.format("Command %s fails", chartResultCmd.getCommandExecuted())); + } +} diff --git a/helm/helm-minimum/src/test/resources/application.properties b/helm/helm-minimum/src/test/resources/application.properties new file mode 100644 index 000000000..cb1bb76fa --- /dev/null +++ b/helm/helm-minimum/src/test/resources/application.properties @@ -0,0 +1,9 @@ + + +# Not supported +#quarkus.openshift.expose=true + +#quarkus.openshift.ports.http.name=pepito +#quarkus.openshift.ports.http.host-port=8080 +#quarkus.openshift.ports.http.container-port=8080 + diff --git a/helm/helm-minimum/src/test/resources/test.properties b/helm/helm-minimum/src/test/resources/test.properties new file mode 100644 index 000000000..72aa68542 --- /dev/null +++ b/helm/helm-minimum/src/test/resources/test.properties @@ -0,0 +1,4 @@ +ts.app.log.enable=false +# generated-service should be set to False on Helm scenarios because we are going to deploy our services through +# Helm instead of using Quarkus Test Framework s2i +ts.global.generated-service.enabled=false diff --git a/pom.xml b/pom.xml index b9c2c78e9..ae1cc29d0 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ 0.11.5 1.15.3 2.13.0 + 0.0.6 1.1.0 1.2.0 3.23.1 @@ -108,6 +109,11 @@ jsoup ${jsoup.version} + + io.quarkiverse.helm + quarkus-helm + ${quarkus-helm.version} + org.assertj assertj-core @@ -389,6 +395,7 @@ logging/jboss cache/caffeine qute/multimodule + helm/helm-minimum