diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ecb6194 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Maven +target +# Maven keycloak.js changes for "war-app-html5" and "war-app-profile-html5" example applications +test-sso/src/test/resources/apps/war-app-html5/src/main/webapp/keycloak.js +test-sso/src/test/resources/apps/war-app-profile-html5/src/main/webapp/keycloak.js + +# Eclipse +.settings +.classpath +.project + +# temp files +log +tmp +log.txt +*.log + +# vim +.*.swp + +# Intellij +.idea/ +*.iml +*.iws + +# Test properties +test.properties + +# Properties used in runtime +used-test.properties + +# Images used in runtime +used-images.properties + +# Templates used for tests +used-templates.properties + +# Usage report +usage.json + +# Indy +infra/maven-cache/indy + +# Ansible +*.retry diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..c32394f --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed 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. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.5"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..0d5e649 Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..fa87ad7 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..70aff5b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018, 2020 ocp-openjdk-test authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d0cc9ca --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# Red Hat OpenJDK OpenShift Container Platform(OCP) Test Suite +*** +This test suite is designed to be executed against current versions of Red Hat's OpenJDK containers. + +| Operating System version | OpenJDK Version | Link to Container | +|--------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------| +| Rhel 7 | 8 | [openjdk18-openshift](https://catalog.redhat.com/software/containers/redhat-openjdk-18/openjdk18-openshift/58ada5701fbe981673cd6b10) | +| Rhel 7 | 11 | [openjdk-11-rhel7](https://catalog.redhat.com/software/containers/openjdk/openjdk-11-rhel7/5bf57185dd19c775cddc4ce5) | +| UBI 8 | 8 | [openjdk-8](https://catalog.redhat.com/software/containers/ubi8/openjdk-8/5dd6a48dbed8bd164a09589a) | +| UBI 8 | 11 | [openjdk-11](https://catalog.redhat.com/software/containers/ubi8/openjdk-11/5dd6a4b45a13461646f677f4) | +| UBI 8 | 17 | [openjdk-17](https://catalog.redhat.com/software/containers/ubi8/openjdk-17/618bdbf34ae3739687568813) | +| UBI 9 | 11 | [openjdk-11](https://catalog.redhat.com/software/containers/ubi9/openjdk-11/61ee7bafed74b2ffb22b07ab) | +| UBI 9 | 17 | [openjdk-17](https://catalog.redhat.com/software/containers/ubi9/openjdk-17/61ee7c26ed74b2ffb22b07f6) | +**Note**: `OpenJDK runtime images are not currently supported by this test suite.` + +*** + + +This test suite is based on the XTF project [https://github.com/xtf-cz/xtf] that leverages JUnit 5, Fabric8 Kubernetes Client [https://github.com/fabric8io/kubernetes-client/] and other useful libraries to unify and simplify interactions with OpenShift. + + +**** + +## Test Execution + +Use `mvn clean` to remove existing test artifacts from your sandbox. + +To execute the UBI 8 or UBI 9 images you must create a (Limit Range) [https://docs.openshift.com/container-platform/4.13/nodes/clusters/nodes-cluster-limit-ranges.html]] +To execute the test suite by hand against a defined version of Red Hat's OpenJDK containers issue the following command. + +* `MAVEN_HOME=/usr/bin/ mvn clean test -P 8 -P smoke -Dmaven.home=/usr/bin/` +* `MAVEN_HOME=/usr/bin/ mvn clean test -P 11 -P smoke -Dmaven.home=/usr/bin/` +* `MAVEN_HOME=/usr/bin/ mvn clean test -P 17 -P smoke -Dmaven.home=/usr/bin/` + +Notice this will execute the test for OpenJDK version 8, 11, or 17. These are the only versions that are supported for testing. To simplify the test execution a `run.sh` has been added. This is the preferred approach to executing tests against the UBI 8 and UBI 9 images. + +For UBI 8 and UBI 9 images it is recommended to use the bash script for the execution of the testsuite. The bash script will create the OCP projects as defined in the `global-test.properties` and then create a limit-range resource as defined by the `limit_range.yaml` file. +```bash +bash run.sh --jdk-version=8 +bash run.sh --jdk-version=11 +bash run.sh --jdk-version=17 +``` + +## Configuration +To configure the test suite for execution against the OpenJDK Image Under Test (IUT) you must have the following. +1. An execution node that can execute a Maven-based Java application. +2. A running instance of Red Hat's OpenShift Container Platform(OCP) with admin access. + +Configure the `global-test.properties` to describe your environment as well as two OCP projects that the test suite runs against. + +```yaml +#mocked settings +xtf.openshift.namespace= +xtf.bm.namespace= +xtf.openshift.url= +xtf.openshift.token= +xtf.openshift.admin.token= +``` + +#### Token auth +``` yaml +#past example +xtf.openshift.url=https://api.servername:6443 +xtf.openshift.token=sha256~lfGBHTDiL1PxVZrM3wMvnU_bvgZyJhZLsb_iU_Zrhwk +xtf.openshift.admin.token=sha256~lfGBHTDiL1PxVZrM3wMvnU_bvgZyJhZLsb_iU_Zrhwk +xtf.openshift.namespace=alpha +xtf.bm.namespace=alpha-builds + +``` + + + diff --git a/global-test.properties b/global-test.properties new file mode 100644 index 0000000..fc980f5 --- /dev/null +++ b/global-test.properties @@ -0,0 +1,19 @@ +############################################# +###### Image Definition with XTF core ####### +############################################# + +# UBI 8 (Rhel 8) version of the container +xtf.openjdk.8.image=registry.access.redhat.com/ubi8/openjdk-8:1.17-1.1693366248 +xtf.openjdk.8.version=1.8.0 + +# UBI 8 (Rhel 8) version of the container +xtf.openjdk.11.image=registry.access.redhat.com/ubi8/openjdk-11:1.17-1.1693366250 +xtf.openjdk.11.version=11 + +#JDK 17 image reference +xtf.openjdk.17.image=registry.access.redhat.com/ubi8/openjdk-17:1.17-1.1693366272 +xtf.openjdk.17.version=17 + +############################################# +xtf.openshift.namespace=jdk +xtf.bm.namespace=jdk-build \ No newline at end of file diff --git a/limit_range.yaml b/limit_range.yaml new file mode 100644 index 0000000..e5d1ddb --- /dev/null +++ b/limit_range.yaml @@ -0,0 +1,13 @@ +apiVersion: "v1" +kind: "LimitRange" +metadata: + name: "openjdk-qe-default-limits" +spec: + limits: + - type: Container + default: + cpu: "2" + memory: 512Mi + defaultRequest: + cpu: "1" + memory: 256Mi \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..d2f0ea3 --- /dev/null +++ b/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# 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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..51d7e00 --- /dev/null +++ b/pom.xml @@ -0,0 +1,287 @@ + + 4.0.0 + com.redhat.openjdk.qe + openjdk + 4.1.0 + pom + Red Hat OpenJDK OCP Test Suite + + + 1.8 + 1.8 + UTF-8 + + + 0.29 + 1.7.32 + 5.12.4 + 1.8.2 + 5.8.2 + 1.18.22 + 3.21.0 + 31.1-jre + 1.2.7 + 1.1.4 + 3.1.0 + 2.11.0 + 1.15 + 3.12.0 + 2.13.0 + + + + 3.1.0 + 3.0.0-M5 + 3.8.1 + + + + test-openjdk + + + + + + + + cz.xtf + core + ${version.xtf} + + + + cz.xtf + builder + ${version.xtf} + + + + cz.xtf + junit5 + ${version.xtf} + + + + cz.xtf + http-client + ${version.xtf} + + + + cz.xtf + test-helpers + ${version.xtf} + + + + io.fabric8 + openshift-client + ${version.io.fabric8.openshift-client} + + + + io.fabric8 + kubernetes-client + ${version.io.fabric8.openshift-client} + + + + io.fabric8 + kubernetes-model + ${version.io.fabric8.openshift-client} + + + + + org.junit.platform + junit-platform-launcher + ${version.junit.platform} + + + + org.junit.jupiter + junit-jupiter-api + ${version.junit.jupiter} + + + + org.junit.jupiter + junit-jupiter-engine + ${version.junit.jupiter} + + + + org.junit.jupiter + junit-jupiter-params + ${version.junit.jupiter} + + + + com.fasterxml.jackson.core + jackson-databind + ${version.jackson-databind} + + + + javax.json + javax.json-api + ${version.javax.json-api} + + + + org.glassfish + javax.json + ${version.javax.json-api} + + + + org.apache.maven.shared + maven-invoker + ${version.maven-invoker} + + + + + org.slf4j + slf4j-api + ${version.org.slf4j} + + + + ch.qos.logback + logback-classic + ${version.logback-classic} + + + + commons-io + commons-io + ${version.commons-io} + + + + commons-codec + commons-codec + ${version.commons-codec} + + + + org.apache.commons + commons-lang3 + ${version.commons-lang3} + + + + com.google.guava + guava + ${version.guava} + + + + org.assertj + assertj-core + ${version.assertj-core} + + + + org.projectlombok + lombok + ${version.lombok} + provided + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${version.maven-compiler-plugin} + + + org.apache.maven.plugins + maven-surefire-plugin + ${version.maven-surefire-plugin} + + + org.apache.maven.plugins + maven-clean-plugin + ${version.maven-clean-plugin} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.apache.maven.plugins + maven-clean-plugin + + + + log + + ** + + + + tmp + + ** + + + + + + + + + + + + + jboss-snapshots-repository + JBoss Snapshots Repository + https://repository.jboss.org/nexus/content/repositories/snapshots + + true + + + false + + + + + jboss-releases-repository + JBoss Releases Repository + https://repository.jboss.org/nexus/content/groups/public/ + + false + + + true + + + + + + + + test-openjdk + + true + + + test-openjdk + + + + + diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..7727068 --- /dev/null +++ b/run.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +############################################################################### +## run.sh +## Entry point for running the Red Hat OpenJDK Container smoketest +## against a Red Hat OpenShift Container Platform +## +############################################################################### + +set -ex +set -o pipefail +## resolve folder of this script, following all symlinks, +## http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in +SCRIPT_SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SCRIPT_SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + SCRIPT_DIR="$( cd -P "$( dirname "$SCRIPT_SOURCE" )" && pwd )" + SCRIPT_SOURCE="$(readlink "$SCRIPT_SOURCE")" + # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located + [[ $SCRIPT_SOURCE != /* ]] && SCRIPT_SOURCE="$SCRIPT_DIR/$SCRIPT_SOURCE" +done +readonly SCRIPT_DIR="$( cd -P "$( dirname "$SCRIPT_SOURCE" )" && pwd )" + +# Help function +function print_help() { + echo "Name: run.sh + Description: Red Hat OpenJDK testsuite for Red Hat OpenShift Container Platform. + Command-line arguements: + --jdk-version + Red Hat OpenJDK version under test. The suite supports versions 8, 11, 17. + Example: run.sh --jdk-version=8" + exit 1 +} + +# OPENJDK_VERSION=<>#Version of OpenJDK under test +# The commandline should be `run.sh --jdk-version=8` +for a in "$@" +do + case $a in + --jdk-version=*) + OPENJDK_VERSION="${a#*=}" + ;; + *) + echo "Unrecognized argument: '$a'" >&2 + print_help >&2 + ;; + esac +done + +# Check the OpenJDK Version to make sure the tests supports it. +if [ $OPENJDK_VERSION -eq 8 ] || [ $OPENJDK_VERSION -eq 11 ] || [ $OPENJDK_VERSION -eq 17 ] ; then + echo "OpenJDK version under test is: $OPENJDK_VERSION" + else + echo "Unsupported OpenJDK version detected." + echo "OpenJDK version is: $OPENJDK_VERSION" + exit 1 +fi + +############################################################################### +## Create the namespace (project) +## In OpenShift a project is similar to a k8s namespace. For the point of +## this test framework's dependencies we will use namespace. +echo "Print the contents of the limit_range yaml file." +cat limit_range.yaml + +NAMESPACE=`cat global-test.properties | grep -Po 'xtf.openshift.namespace=\K[^ ]+'` +BUILD_NAMESPACE=`cat global-test.properties | grep -Po 'xtf.bm.namespace=\K[^ ]+'` +LIMIT_RANGE_NAME=`cat limit_range.yaml | grep -Po 'name:\s\K[^ ]+'| tr -d '"'` + +echo "Namespace check $NAMESPACE And $BUILD_NAMESPACE" + +for PROJECTNAME in "$NAMESPACE" "$BUILD_NAMESPACE" +do + echo "Projectname: $PROJECTNAME" + set +e + oc get project "$PROJECTNAME" > /dev/null 2>&1 + if [ "$?" -eq 0 ] ; then + echo "Project: $PROJECTNAME already exists proceed." + # Check that the limitranges resource exists. + oc get limitranges -A | grep -P "${PROJECTNAME}\s*${LIMIT_RANGE_NAME}" + if [ "$?" -eq 0 ] ; then + echo " " + echo "Namespace $PROJECTNAME already has a limitranges applied named $LIMIT_RANGE_NAME" + echo " " + else + oc create -f limit_range.yaml -n $PROJECTNAME + fi + else + # Create the project + oc new-project $PROJECTNAME + # Create the limitranges resource for this project + oc create -f limit_range.yaml -n $PROJECTNAME + fi + set -e +done + +echo "Now output the projects under test and any other resource." +oc get limitranges -A + +## Run the testsuite + +MAVEN_HOME=/usr/share/maven mvn clean test -P $OPENJDK_VERSION -P smoke -Dmaven.home=/usr/share/maven + +############################################################################## + +#OPENJDK_VERSION +# MAVEN_HOME=/usr/share/maven mvn clean test -P 8 -P smoke -Dmaven.home=/usr/share/maven +# MAVEN_HOME=/usr/share/maven mvn clean test -P 11 -P smoke -Dmaven.home=/usr/share/maven +# MAVEN_HOME=/usr/share/maven mvn clean test -P 17 -P smoke -Dmaven.home=/usr/share/maven diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..6dd55f2 --- /dev/null +++ b/settings.xml @@ -0,0 +1,68 @@ + + + + redhat-ga-repository + + + jboss-ga-repository + https://maven.repository.redhat.com/ga/ + + true + + + false + + + + + + + jboss-ga-plugin-repository + https://maven.repository.redhat.com/ga/ + + true + always + + + false + + + + + + + redhat-ea-repository + + + redhat-ea-repository + https://maven.repository.redhat.com/earlyaccess/all/ + + true + always + + + true + always + + + + + + redhat-ea-plugin-repository + https://maven.repository.redhat.com/earlyaccess/all/ + + true + + + true + + + + + + + + redhat-ga-repository + redhat-ea-repository + + \ No newline at end of file diff --git a/test-openjdk/pom.xml b/test-openjdk/pom.xml new file mode 100644 index 0000000..7d931a7 --- /dev/null +++ b/test-openjdk/pom.xml @@ -0,0 +1,244 @@ + + + + openjdk + com.redhat.openjdk.qe + 4.1.0 + + 4.0.0 + + test-openjdk + OpenJdkQe Test Suite :: OpenJDK + + + 2.6.1 + 4.4.0 + + 8 + + + EMPTY + EMPTY + false + + + + + cz.xtf + core + test + + + + cz.xtf + http-client + test + + + + cz.xtf + builder + test + + + + cz.xtf + test-helpers + test + + + + cz.xtf + junit5 + test + + + + io.fabric8 + openshift-client + + + + io.fabric8 + kubernetes-client + + + + io.fabric8 + kubernetes-model + + + + com.fasterxml.jackson.core + jackson-databind + test + + + + javax.json + javax.json-api + test + + + + org.glassfish + javax.json + test + + + + org.apache.maven.shared + maven-invoker + test + + + + + commons-io + commons-io + test + + + + commons-codec + commons-codec + test + + + + org.apache.commons + commons-lang3 + test + + + + + org.junit.platform + junit-platform-launcher + test + + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.junit.jupiter + junit-jupiter-engine + test + + + + org.junit.jupiter + junit-jupiter-params + test + + + + org.assertj + assertj-core + test + + + + org.projectlombok + lombok + provided + + + + org.slf4j + slf4j-api + test + + + + ch.qos.logback + logback-classic + + + + com.google.guava + guava + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + ${groups} + ${excludedGroupsVersions}, ${excludedGroups} + false + false + filesystem + + openjdk + ${xtf.openjdk.subid} + dns,sun + default + ${test.script.debug} + + + + + + + + + 8 + + 8 + + + + 11 + + 11 + + + + 17 + + 17 + + + + smoke + + smoke + + + + + multiarch + + multiarch + + + + + + 1.8 + + + + + com.sun + tools + ${maven.compiler.target} + system + ${java.home}/../lib/tools.jar + + + + + diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/OpenJDKTestConfig.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/OpenJDKTestConfig.java new file mode 100644 index 0000000..92aedd5 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/OpenJDKTestConfig.java @@ -0,0 +1,91 @@ +package com.redhat.qe.openjdk; + +import org.apache.commons.lang3.StringUtils; + +import cz.xtf.core.config.XTFConfig; +import cz.xtf.core.image.Image; +import cz.xtf.core.image.Product; +import cz.xtf.core.image.Products; + +public class OpenJDKTestConfig { + + + public static Product product() { + return Products.resolve("openjdk"); + } + + public static Image image() { + return product().image(); + } + + public static String getProductVersion() { + return product().version(); + } + + public static String getImageUrl(){ + return image().getUrl(); + } + + public static String imageUrl() { + return image().getUrl(); + } + + public static String getImageRepo() { + return image().getRepo(); + } + + public static boolean isOpenJDK8() { + return image().getRepo().contains("openjdk-8"); + } + + public static boolean isOpenJDK11() { + return image().getRepo().contains("openjdk-11"); + } + public static boolean isOpenJDK17() { + return image().getRepo().contains("openjdk-17"); + } + + // Need to spell out the Rhel 7-based builds because they do not follow the newer + // naming conventions. + public static boolean isOpenJDK8Rhel7() { + return image().getRepo().contains("openjdk18-openshift"); + } + public static boolean isOpenJDK11Rhel7() { + return image().getRepo().contains("openjdk-11-rhel7"); + } + public static boolean isRHEL7() { + boolean check = false; + if (getImageUrl().contains("openjdk-11-rhel7")) { + check = true; + } + if (getImageUrl().contains("openjdk18-openshift")) { + check = true; + } + return check; + } + + public static boolean isRHEL8() { + return getImageUrl().contains("ubi8"); + } + + public static boolean isRHEL9() { + return getImageUrl().contains("ubi9"); + } + + public static boolean isOpenJ9() { + return image().getRepo().contains("openj9-"); + } + + public static boolean isMavenProxyEnabled() { + return mavenProxyUrl() != null; + } + + public static String mavenProxyUrl() { + final String url = XTFConfig.get("xtf.maven.proxy.url"); + if (!StringUtils.isBlank(url)) { + return url.trim(); + } + return null; + } + +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/OpenJDKTestParent.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/OpenJDKTestParent.java new file mode 100644 index 0000000..a53fcf5 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/OpenJDKTestParent.java @@ -0,0 +1,174 @@ +package com.redhat.qe.openjdk; + +import com.redhat.qe.openjdk.util.maven.PomModifier; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveException; +import org.apache.commons.compress.archivers.ArchiveOutputStream; +import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.filefilter.TrueFileFilter; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.Collection; +import java.util.Date; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import cz.xtf.builder.builders.ApplicationBuilder; +import cz.xtf.core.openshift.OpenShifts; +import io.fabric8.openshift.api.model.Build; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class OpenJDKTestParent { + + protected static final Path TMP_SOURCES_DIR = Paths.get("tmp").toAbsolutePath().resolve("sources"); + protected static final String SUITE_NAME = "test-openjdk"; + + public static Path findProjectRoot() { + Path dir = Paths.get("").toAbsolutePath(); + for (; dir.getParent().resolve("pom.xml").toFile().exists(); dir = dir.getParent()) ; + return dir; + } + + public static Path prepareProjectSources(final String appName, final Path projectDir) throws IOException { + if (projectDir == null) { + return null; + } + + Files.createDirectories(TMP_SOURCES_DIR); + Path sourcesDir = Files.createTempDirectory(TMP_SOURCES_DIR.toAbsolutePath(), appName); + FileUtils.copyDirectory(projectDir.toFile(), sourcesDir.toFile()); + + new PomModifier().modify(projectDir, sourcesDir); + + return sourcesDir; + } + + public static ApplicationBuilder appFromBinaryBuild(final String appName) { + ApplicationBuilder appBuilder = new ApplicationBuilder(appName); + appBuilder.buildConfig().setOutput(appName).sti().forcePull(true).fromDockerImage(OpenJDKTestConfig.imageUrl()); + appBuilder.imageStream(); + appBuilder.deploymentConfig().onImageChange().onConfigurationChange().podTemplate().container().fromImage(appName); + + appBuilder.buildConfig().withBinaryBuild(); + if (OpenJDKTestConfig.isMavenProxyEnabled()) { + appBuilder.buildConfig().sti().addEnvVariable("MAVEN_MIRROR_URL", OpenJDKTestConfig.mavenProxyUrl()); + } + + return appBuilder; + } + + public static Path findApplicationDirectory(String appName) { + return findApplicationDirectory(SUITE_NAME, appName, null); + } + + public static Path findApplicationDirectory(String appName, String appModuleName) { + return findApplicationDirectory(SUITE_NAME, appName, appModuleName); + } + + public static Path findApplicationDirectory(String moduleName, String appName, String appModuleName) { + Path path; + path = FileSystems.getDefault().getPath("src/test/resources/apps", appName); + + /* We only return this path if the absolute path contains the moduleName, + e.g. if both test-eap and test-common contain "foo", but we explicitly want + the test-common/src/test/resources/apps/foo + */ + if (Files.exists(path) && path.toAbsolutePath().toString().contains(moduleName)) { + return path; + } + log.debug("Path {} does not exist", path.toAbsolutePath()); + if (appModuleName != null) { + path = FileSystems.getDefault().getPath("src/test/resources/apps/" + appModuleName, appName); + if (Files.exists(path) && path.toAbsolutePath().toString().contains(moduleName)) { + return path; + } + log.info("Path {} does not exist", path.toAbsolutePath()); + } + path = FileSystems.getDefault().getPath(moduleName + "/src/test/resources/apps", appName); + if (Files.exists(path)) { + return path; + } + log.info("Path {} does not exist", path.toAbsolutePath()); + if (appModuleName != null) { + path = FileSystems.getDefault().getPath(moduleName + "/src/test/resources/apps/" + appModuleName, appName); + if (Files.exists(path) && path.toAbsolutePath().toString().contains(moduleName)) { + return path; + } + log.info("Path {} does not exist", path.toAbsolutePath()); + } + path = FileSystems.getDefault().getPath("../" + moduleName + "/src/main/resources/apps", appName); + if (Files.exists(path)) { + return path; + } + log.info("Path {} does not exist", path.toAbsolutePath()); + path = FileSystems.getDefault().getPath("../" + moduleName + "/src/test/resources/apps", appName); + if (Files.exists(path)) { + return path; + } + log.info("Path {} does not exist", path.toAbsolutePath()); + throw new IllegalArgumentException("Cannot find directory with STI app sources"); + } + + public static Build startBinaryBuild(final String bcName, Path sources) throws IOException { + try { + PipedOutputStream pos = new PipedOutputStream(); + PipedInputStream pis = new PipedInputStream(pos); + + ExecutorService executorService = Executors.newSingleThreadExecutor(); + final Future future = executorService.submit(() -> { + Collection filesToArchive = FileUtils.listFiles(sources.toFile(), TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); + try (ArchiveOutputStream o = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.TAR, pos)) { + for (File f : filesToArchive) { + String tarPath = sources.relativize(f.toPath()).toString(); + log.trace("adding file to tar: {}", tarPath); + ArchiveEntry entry = o.createArchiveEntry(f, tarPath); + + // we force the modTime in the tar, so that the resulting tars are binary equal if their contents are + TarArchiveEntry tarArchiveEntry = (TarArchiveEntry)entry; + tarArchiveEntry.setModTime(Date.from(Instant.EPOCH)); + + o.putArchiveEntry(tarArchiveEntry); + if (f.isFile()) { + try (InputStream i = Files.newInputStream(f.toPath())) { + IOUtils.copy(i, o); + } + } + o.closeArchiveEntry(); + } + + o.finish(); + } catch (ArchiveException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + Build ret = OpenShifts.master().buildConfigs().withName(bcName).instantiateBinary().fromInputStream(pis); + future.get(); + + return ret; + } catch (InterruptedException e) { + log.error("IOException building {}", bcName, e); + throw new RuntimeException(e); + } catch (ExecutionException e) { + log.error("IOException building {}", bcName, e); + throw new RuntimeException(e); + } + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/common/AbstractEnvVarsTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/common/AbstractEnvVarsTest.java new file mode 100644 index 0000000..3e0f308 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/common/AbstractEnvVarsTest.java @@ -0,0 +1,81 @@ +package com.redhat.qe.openjdk.common; + +import org.junit.jupiter.api.BeforeEach; +import com.redhat.qe.openjdk.jolokia.JolokiaConfiguration; +import com.redhat.qe.openjdk.util.deployment.MsaDeploymentBuilder; +import org.junit.platform.commons.util.StringUtils; + +import com.redhat.qe.openjdk.OpenJDKTestParent; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import cz.xtf.builder.builders.limits.ComputingResource; +import cz.xtf.builder.builders.pod.ContainerBuilder; +import cz.xtf.core.bm.ManagedBuild; +import cz.xtf.core.openshift.OpenShift; +import cz.xtf.core.openshift.OpenShifts; +import cz.xtf.junit5.annotations.CleanBeforeEach; + +@CleanBeforeEach +public abstract class AbstractEnvVarsTest extends OpenJDKTestParent { + public static final String APP_NAME = "test-app"; + protected static final OpenShift openshift = OpenShifts.master(); + + + protected void deploy(final ManagedBuild build) { + this.deploy(build, Collections.emptyMap()); + } + + protected void deploy(final ManagedBuild build, final Map envVars) { + deploy(build, envVars, null, null); + } + + protected void deploy(final ManagedBuild build, final Map envVars, + final ComputingResource cpuResource, final ComputingResource memoryResource) { + deploy(build, envVars, cpuResource, memoryResource, new JolokiaConfiguration.Builder().build()); + } + + protected void deploy(final ManagedBuild build, final Map envVars, + final ComputingResource cpuResource, final ComputingResource memoryResource, + final JolokiaConfiguration jolokaConf) { + deploy(build, envVars, cpuResource, memoryResource, jolokaConf, null); + } + + protected void deploy(final ManagedBuild build, final Map envVars, + final ComputingResource cpuResource, final ComputingResource memoryResource, + final JolokiaConfiguration jolokaConf, final Consumer containerModification) { + MsaDeploymentBuilder.withNewJavaS2IApp(APP_NAME) + .withBuild(build) + .generateMirrorSettings(false) + .withDeploymentEnvironmentVariables(envVars) + .withCPUResource(cpuResource) + .withMemoryResource(memoryResource) + .urlCheck("") + .withContainerModification(containerModification) + .configureJolokia(jolokaConf) + .deploy(); + } + + protected List getJavaOpts() { + final String cmdline = openshift.podShell(APP_NAME).executeWithBash(String.format("cat /proc/%s/cmdline", getPid(APP_NAME))).getOutput(); + char delimiter = '\u0000'; // = "\\0" + return Arrays.asList(cmdline.split(String.valueOf(delimiter))); + } + protected List getPodEnv() { + final String cmdline = openshift.podShell(APP_NAME).executeWithBash(String.format("cat /proc/%s/environ", getPid(APP_NAME))).getOutput(); + char delimiter = '\u0000'; // = "\\0" + return Arrays.asList(cmdline.split(String.valueOf(delimiter))); + } + + protected String getPid(String appName) { + String output = openshift.podShell(appName).executeWithBash("ps -C java -o pid | grep [0-9]").getOutput(); + if (StringUtils.isBlank(output)) { + output = openshift.podShell(appName).executeWithBash("grep java -l /proc/*/exe | cut -d \"/\" -f 3").getOutput(); + } + return output; + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/image/AbstractDockerImageTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/image/AbstractDockerImageTest.java new file mode 100644 index 0000000..3335ee8 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/image/AbstractDockerImageTest.java @@ -0,0 +1,114 @@ +package com.redhat.qe.openjdk.image; + + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.assertj.core.api.Assertions; + +import com.redhat.qe.openjdk.OpenJDKTestConfig; +import com.redhat.qe.openjdk.OpenJDKTestParent; + +import java.util.List; +import java.util.stream.Collectors; + +import cz.xtf.core.openshift.OpenShift; +import cz.xtf.core.openshift.OpenShifts; +import cz.xtf.testhelpers.image.ImageContent; +import cz.xtf.testhelpers.image.ImageMetadata; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public abstract class AbstractDockerImageTest extends OpenJDKTestParent { + public static final String JBOSS_PRODUCT = "org.jboss.product"; + public static final String JBOSS_PRODUCT_VERSION = "org.jboss.product.version"; + public static final String JBOSS_PRODUCT_JDK_VERSION = "org.jboss.product.openjdk.version"; + private static final Logger LOGGER = LoggerFactory.getLogger(DockerImageTest.class); + + public static final String[] DEFAULT_JAVA_8_UTILITIES = new String[]{ + "alt-java", "appletviewer", "clhsdb", "extcheck", + "hsdb", "idlj", "jar", "jarsigner", "java", + "java-rmi.cgi", "javac", "javadoc", "javah", + "javap", "jcmd", "jconsole", "jdb", + "jdeps", "jfr", "jhat", "jinfo", "jjs", + "jmap", "jps", "jrunscript", "jsadebugd", + "jstack", "jstat", "jstatd", "keytool", + "native2ascii", "orbd", "pack200", "policytool", + "rmic", "rmid", "rmiregistry", "schemagen", + "serialver", "servertool", "tnameserv", + "unpack200", "wsgen", "wsimport", "xjc" + }; + public static final String[] DEFAULT_JAVA_11_UTILITIES = new String[]{ + "alt-java", "jaotc", "jar", "jarsigner", "java", + "javac", "javadoc", "javap", "jcmd", "jconsole", + "jdb", "jdeprscan", "jdeps", "jfr", "jhsdb", + "jimage", "jinfo", "jjs", "jlink", "jmap", + "jmod", "jps", "jrunscript", "jshell", "jstack", + "jstat", "jstatd", "keytool", "pack200", "rmic", + "rmid", "rmiregistry", "serialver", "unpack200" + }; + public static final String[] DEFAULT_JAVA_17_UTILITIES = new String[]{ + "alt-java", "jar", "jarsigner", "java", "javac", + "javadoc", "javap", "jcmd", "jconsole", "jdb", + "jdeprscan", "jdeps", "jfr", "jhsdb", "jimage", + "jinfo", "jlink", "jmap", "jmod", "jpackage", + "jps", "jrunscript", "jshell", "jstack", "jstat", + "jstatd", "keytool", "rmiregistry", "serialver" + }; + + public static final String RED_HAT_RELEASE_KEY_2 = "199e2f91fd431d51"; + + protected static final OpenShift openShift = OpenShifts.master(); + + protected static ImageMetadata metadata; + protected static ImageContent content; + + @BeforeAll + public static void cleanNamespace() { + openShift.clean().waitFor(); + } + + @Test + public void packageSigningTest() { + // https://access.redhat.com/security/team/key + List unsignedRpms = content.rpms().stream().filter(rpm -> !rpm.getSignature().endsWith(RED_HAT_RELEASE_KEY_2)).collect(Collectors.toList()); + + if(unsignedRpms.size() > 0) { + Assertions.assertThat(unsignedRpms).hasSize(2); + if (OpenJDKTestConfig.isRHEL9()){ + Assertions.assertThat(unsignedRpms.stream().map(x -> x.getName() + "-" + x.getVersion() + "-" + x.getRelease())) + .containsExactlyInAnyOrder("gpg-pubkey-5a6340b3-6229229e", ImageContent.RED_HAT_RELEASE_KEY_2_RPM); + } + else if (OpenJDKTestConfig.isRHEL8()) { + Assertions.assertThat(unsignedRpms.stream().map(x -> x.getName() + "-" + x.getVersion() + "-" + x.getRelease())) + .containsExactlyInAnyOrder("gpg-pubkey-d4082792-5b32db75", ImageContent.RED_HAT_RELEASE_KEY_2_RPM); + } else { + Assertions.assertThat(unsignedRpms.stream().map(x -> x.getName() + "-" + x.getVersion() + "-" + x.getRelease())) + .containsExactlyInAnyOrder(ImageContent.RED_HAT_AUXILIARY_KEY_RPM, ImageContent.RED_HAT_RELEASE_KEY_2_RPM); + } + } + } + + @Test + public void illegalRepositoriesTest() { + if (OpenJDKTestConfig.isRHEL8() || OpenJDKTestConfig.isRHEL9()) { + LOGGER.info("DockerImageTest:illegalRepositoriesTest::This test is checking against UBI8 or UBI9 image." ); + Assertions.assertThat(content.listDirContent("/etc/yum.repos.d/")).containsExactly("redhat.repo", "ubi.repo"); + } else { + LOGGER.info("DockerImageTest:illegalRepositoriesTest::This test is checking against a Rhel7-based image." ); + Assertions.assertThat(content.listDirContent("/etc/yum.repos.d/")).isEmpty(); + } + } + + @Test + public void javaUtilitiesTest() { + // This should only be called for an unsupported JDK. Every other version should be handled in the DockerImageTest file. + Assertions.assertThat(content.listDirContent("$JAVA_HOME/bin")).contains("NOTSUPPORTED"); + } + + @Test + public abstract void javaVersionTest(); + +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/image/DockerImageTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/image/DockerImageTest.java new file mode 100644 index 0000000..a77792f --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/image/DockerImageTest.java @@ -0,0 +1,220 @@ +package com.redhat.qe.openjdk.image; + +import com.redhat.qe.openjdk.util.annotation.JavaS2IProfile; +import com.redhat.qe.openjdk.util.annotation.MultiArchProfile; +import com.redhat.qe.openjdk.util.annotation.SmokeTest; +import cz.xtf.core.config.WaitingConfig; +import cz.xtf.core.waiting.SimpleWaiter; +import io.fabric8.kubernetes.api.model.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.assertj.core.api.Assertions; + +import com.redhat.qe.openjdk.OpenJDKTestConfig; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BooleanSupplier; +import java.util.regex.Pattern; + +import cz.xtf.core.openshift.OpenShift; +import cz.xtf.core.openshift.OpenShifts; +import cz.xtf.testhelpers.image.ImageContent; +import cz.xtf.testhelpers.image.ImageMetadata; +import cz.xtf.core.openshift.helpers.ResourceParsers; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Slf4j +@JavaS2IProfile +@MultiArchProfile +@SmokeTest + + +public class DockerImageTest extends AbstractDockerImageTest { + private static final OpenShift openShift = OpenShifts.master(); + + private static final String project = openShift.getNamespace(); + + private static final Map EXPECTED_ENVIRONMENTS = getExpectedEnvironments(); + + private static final Logger LOGGER = LoggerFactory.getLogger(DockerImageTest.class); + + @BeforeAll + public static void prepareImage() { + metadata = ImageMetadata.prepare(openShift, OpenJDKTestConfig.imageUrl()); + // Override default pod command `run-java.sh` to start without jar file present + // Attempt to replace functionality from the xtf framework. + String name = "test-pod"; + Container container = new ContainerBuilder().withName(name).withImage(OpenJDKTestConfig.imageUrl()).build(); + SeccompProfile secCom = new SeccompProfile(); + secCom.setType("RuntimeDefault"); + Capabilities cap = new Capabilities(); + cap.setDrop(Arrays.asList("ALL")); + SecurityContext secContext = container.getSecurityContext(); + container.setCommand(Arrays.asList("/bin/bash", "-c", "sleep infinity")); + + SecurityContext updateSecContext = new SecurityContext(); + updateSecContext.setAllowPrivilegeEscalation(false); + updateSecContext.setRunAsNonRoot(true); + updateSecContext.setSeccompProfile(secCom); + updateSecContext.setCapabilities(cap); + // Apply the security context to the container object. + container.setSecurityContext(updateSecContext); + PodSpec podSpec = new PodSpec(); + podSpec.setContainers(Collections.singletonList(container)); + Pod pod = new Pod(); + pod.setMetadata(new ObjectMetaBuilder().withName(name).build()); + pod.setSpec(podSpec); + openShift.createPod(pod); + BooleanSupplier bs = () -> { + Pod p = openShift.getPod(name); + return p != null && ResourceParsers.isPodRunning(p) && ResourceParsers.isPodReady(p); + }; + new SimpleWaiter(bs, "Waiting for '" + name + "' pod to be running and ready").timeout(WaitingConfig.timeout()) + .waitFor(); + content = ImageContent.prepare(openShift, pod); + + SecurityContext correctSecContext = new SecurityContext(); + + LOGGER.info("########### Image Under Test: " + OpenJDKTestConfig.getImageUrl() ); + LOGGER.info("########### Product version Under Test: " + OpenJDKTestConfig.getProductVersion() ); + LOGGER.info("########### Repo Under Test: " + OpenJDKTestConfig.getImageRepo() ); + LOGGER.info("########### Java Version Under Test: " + content.javaVersion()); + LOGGER.info("########### Java Version Under Test error RAW: " + content.shell().execute(new String[]{"java", "-version"}).getError().replaceAll("\n", "") ); + } + + @Test + public void testCorrectCommand() { + Assertions.assertThat(metadata.command()).isEqualTo("/usr/local/s2i/run"); + } + + @Test + public void testDeclaredEnvironmentVariables() { + Assertions.assertThat(metadata.envs()).containsAllEntriesOf(EXPECTED_ENVIRONMENTS); + } + + @Test + public void testEnvironmentVariablesInContainer() { + Assertions.assertThat(content.runtimeEnvVars()).containsAllEntriesOf(EXPECTED_ENVIRONMENTS); + } + + @Test + public void testExposedTcpPorts() { + // Port 8778 is from Jolokia and this has been pulled from the JDK17 containers. + // This port has also been removed from the ubi9 images. + if ( OpenJDKTestConfig.isOpenJDK17() || OpenJDKTestConfig.isRHEL9()) { + Assertions.assertThat(metadata.exposedPorts("tcp")).containsOnly(8080, 8443); + } else { + Assertions.assertThat(metadata.exposedPorts("tcp")).containsOnly(8080, 8443, 8778); + } + + } + + @Test + public void testExposedUdpPorts() { + Assertions.assertThat(metadata.exposedPorts("udp")).hasSize(0); + } + + @Test + public void testUsageLabel() { + + if (OpenJDKTestConfig.isRHEL7()){ + Assertions.assertThat(metadata.labels().get("usage")).isEqualTo("https://access.redhat.com/documentation/en-us/red_hat_jboss_middleware_for_openshift/3/html/red_hat_java_s2i_for_openshift/"); + } else if( OpenJDKTestConfig.isOpenJDK8() ) { + Assertions.assertThat(metadata.labels().get("usage")).isEqualTo("https://access.redhat.com/documentation/en-us/openjdk/8/html/using_openjdk_8_source-to-image_for_openshift/index"); + } else if (OpenJDKTestConfig.isOpenJDK11()){ + Assertions.assertThat(metadata.labels().get("usage")).isEqualTo("https://access.redhat.com/documentation/en-us/openjdk/11/html/using_openjdk_11_source-to-image_for_openshift/index"); + } else if (OpenJDKTestConfig.isOpenJDK17()){ + Assertions.assertThat(metadata.labels().get("usage")).isEqualTo("https://access.redhat.com/documentation/en-us/red_hat_jboss_middleware_for_openshift/3/html/red_hat_java_s2i_for_openshift/"); + } + + } + + @Test + public void testUrandomJavaSecurity() { + String result = "none"; + if ( OpenJDKTestConfig.isOpenJDK8() || OpenJDKTestConfig.isOpenJDK8Rhel7() ) { + result = content.shell().execute("cat", "/usr/lib/jvm/java/jre/lib/security/java.security").getOutput(); + } else if (OpenJDKTestConfig.isOpenJDK11()){ + result = content.shell().execute("cat", "/usr/lib/jvm/jre/conf/security/java.security").getOutput(); + } else if (OpenJDKTestConfig.isOpenJDK17()){ + result = content.shell().execute("cat", "/usr/lib/jvm/jre/conf/security/java.security").getOutput(); + } + + Assertions.assertThat(result).containsPattern( + Pattern.compile("^securerandom.source=file:/dev/urandom$", Pattern.MULTILINE)); + } + + @Override + @Test + public void javaUtilitiesTest() { + //Content should match what is in the java/bin folder. Or the $JAVA_HOME/bin folder + if ( OpenJDKTestConfig.isOpenJDK8() || OpenJDKTestConfig.isOpenJDK8Rhel7() ) { + LOGGER.info("DockerImageTest:javaUtilitiesTest::Running check for jdk8."); + Assertions.assertThat(content.listDirContent("$JAVA_HOME/bin")).contains(super.DEFAULT_JAVA_8_UTILITIES); + } else if (OpenJDKTestConfig.isOpenJDK11()){ + LOGGER.info("DockerImageTest:javaUtilitiesTest::Running check for jdk11."); + Assertions.assertThat(content.listDirContent("$JAVA_HOME/bin")).contains(super.DEFAULT_JAVA_11_UTILITIES); + } else if (OpenJDKTestConfig.isOpenJDK17()){ + LOGGER.info("DockerImageTest:javaUtilitiesTest::Running check for jdk17"); + Assertions.assertThat(content.listDirContent("$JAVA_HOME/bin")).contains(super.DEFAULT_JAVA_17_UTILITIES); + } + else { + LOGGER.info("DockerImageTest:javaUtilitiesTest::Error, jdk version not supported. Please check jdk container image."); + super.javaUtilitiesTest(); + } + + } + + @Override + @Test + public void javaVersionTest() { + Assertions.assertThat(content.javaVersion()).contains(OpenJDKTestConfig.product().version()); + } + + + private static Map getExpectedEnvironments() { + final Map result = new HashMap<>(); + // With the ubi9 (RHEL 9) images the user has been changed from /home/jboss to /home/default/ + if (OpenJDKTestConfig.isRHEL9()) { + result.put("HOME", "/home/default"); + } else { + result.put("HOME", "/home/jboss"); + } + + if (OpenJDKTestConfig.isOpenJ9()) { + result.put("JAVA_HOME", OpenJDKTestConfig.isOpenJDK11() ? "/usr/lib/jvm/jre-11-openj9" : "/usr/lib/jvm/jre-1.8.0-openj9"); + } else if (OpenJDKTestConfig.isOpenJDK17()) { + result.put("JAVA_HOME", "/usr/lib/jvm/java-17"); + } else { + result.put("JAVA_HOME", OpenJDKTestConfig.isOpenJDK11() ? "/usr/lib/jvm/java-11" : "/usr/lib/jvm/java-1.8.0"); + } + result.put("JAVA_VENDOR", OpenJDKTestConfig.isOpenJ9() ? "AdoptOpenJDK" : "openjdk"); + if (OpenJDKTestConfig.isOpenJDK17()) { + result.put("JAVA_VERSION", "17"); + } else { + result.put("JAVA_VERSION", OpenJDKTestConfig.isOpenJDK11() ? "11" : "1.8.0"); + // With ubi9, Jolokia was removed from all images. + if (!OpenJDKTestConfig.isRHEL9()) { + result.put("JOLOKIA_VERSION", "1.6.2"); + result.put("AB_JOLOKIA_PASSWORD_RANDOM", "true"); + result.put("AB_JOLOKIA_AUTH_OPENSHIFT", "true"); + } + } + if (OpenJDKTestConfig.isRHEL7()) { + result.put("MAVEN_VERSION", "3.6"); + } else { + result.put("MAVEN_VERSION", "3.8"); + } + + + result.put("JAVA_DATA_DIR", "/deployments/data"); + + return Collections.unmodifiableMap(result); + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/jolokia/JolokiaConfiguration.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/jolokia/JolokiaConfiguration.java new file mode 100644 index 0000000..ad6e91c --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/jolokia/JolokiaConfiguration.java @@ -0,0 +1,113 @@ +package com.redhat.qe.openjdk.jolokia; + +import lombok.Getter; + +@Getter +public class JolokiaConfiguration { + private final boolean enabled; + private final String configFile; + private final boolean randomPassword; + private final String user; + private final String password; + private final String host; + private final int port; + private final boolean discoveryEnabled; + private final String https; + private final boolean authOpenShift; + private final String additionalOpts; + private final String portName; + + public JolokiaConfiguration(final Builder builder) { + this.enabled = builder.enabled; + this.configFile = builder.configFile; + this.randomPassword = builder.randomPassword; + this.user = builder.user; + this.password = builder.password; + this.host = builder.host; + this.port = builder.port; + this.discoveryEnabled = builder.discoveryEnabled; + this.https = builder.https; + this.authOpenShift = builder.authOpenShift; + this.additionalOpts = builder.additionalOpts; + this.portName = builder.portName; + } + + public static class Builder { + private boolean enabled = true; + private String configFile = ""; + private boolean randomPassword = true; + private String user = "jolokia"; + private String password = ""; + private String host = "*"; + private int port = 8778; + private boolean discoveryEnabled = false; + private String https = ""; + private boolean authOpenShift = true; + private String additionalOpts = ""; + private String portName = "jolokia"; + + public Builder enabled(final boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder configFile(final String configFile) { + this.configFile = configFile; + return this; + } + + public Builder randomPassword(final boolean randomPassword) { + this.randomPassword = randomPassword; + return this; + } + + public Builder user(final String user) { + this.user = user; + return this; + } + + public Builder password(final String password) { + this.password = password; + return this; + } + + public Builder host(final String host) { + this.host = host; + return this; + } + + public Builder port(final int port) { + this.port = port; + return this; + } + + public Builder discoveryEnabled(final boolean discoveryEnabled) { + this.discoveryEnabled = discoveryEnabled; + return this; + } + + public Builder https(final String https) { + this.https = https; + return this; + } + + public Builder authOpenShift(final boolean authOpenShift) { + this.authOpenShift = authOpenShift; + return this; + } + + public Builder additionalOpts(final String additionalOpts) { + this.additionalOpts = additionalOpts; + return this; + } + + public Builder portName(final String portName) { + this.portName = portName; + return this; + } + + public JolokiaConfiguration build() { + return new JolokiaConfiguration(this); + } + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/maven/MavenJavaArgsTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/maven/MavenJavaArgsTest.java new file mode 100644 index 0000000..001a82a --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/maven/MavenJavaArgsTest.java @@ -0,0 +1,229 @@ +package com.redhat.qe.openjdk.maven; + +import com.redhat.qe.openjdk.util.annotation.JavaS2IProfile; +import com.redhat.qe.openjdk.util.annotation.MultiArchProfile; +import com.redhat.qe.openjdk.util.annotation.SmokeTest; +import com.redhat.qe.openjdk.util.build.JavaS2IBuild; +import com.redhat.qe.openjdk.util.build.UsesJavaS2IBuilds; +import com.redhat.qe.openjdk.OpenJDKTestConfig; +import com.redhat.qe.openjdk.common.AbstractEnvVarsTest; +import cz.xtf.builder.builders.ApplicationBuilder; +import cz.xtf.junit5.annotations.KnownIssue; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.Assertions; +import org.assertj.core.api.Condition; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; + +import org.junit.jupiter.api.condition.DisabledIf; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +@JavaS2IProfile +@MultiArchProfile +@Slf4j +@SmokeTest +@UsesJavaS2IBuilds({JavaS2IBuild.JAVA_APP_DIR_NAME, JavaS2IBuild.MAVEN_CLEAR_REPO, JavaS2IBuild.JAVA_OPTIONS, JavaS2IBuild.JAVA_ARGS, JavaS2IBuild.JAVA_APP_NAME, JavaS2IBuild.JAVA_REGULAR_JAR_WITH_CLASSPATH_FILE}) +public class MavenJavaArgsTest extends AbstractEnvVarsTest { + private static final Logger LOGGER = LoggerFactory.getLogger(MavenJavaArgsTest.class); + + @Test + public void testMavenArgs() throws IOException { + // Don't use BuildManager to pre-build this app. We need to make sure logs are accessible for assertion. + startLocalBuild(JavaS2IBuild.MAVEN_ARGS.getBuildDefinition().getBuildName(), JavaS2IBuild.MAVEN_ARGS.getBuildDefinition() + .getEnvProperties()); + openshift.waiters().hasBuildCompleted(JavaS2IBuild.MAVEN_ARGS.getBuildDefinition().getBuildName()).waitFor(); + + verifyLocalBuildLog(JavaS2IBuild.MAVEN_ARGS, JavaS2IBuild.MAVEN_ARGS.getBuildDefinition() + .getEnvProperties() + .get("MAVEN_ARGS")); + } + + @Test + public void testMavenArgsAppend() throws IOException { + startLocalBuild(JavaS2IBuild.MAVEN_ARGS_APPEND.getBuildDefinition().getBuildName(), JavaS2IBuild.MAVEN_ARGS_APPEND.getBuildDefinition() + .getEnvProperties()); + openshift.waiters().hasBuildCompleted(JavaS2IBuild.MAVEN_ARGS_APPEND.getBuildDefinition().getBuildName()).waitFor(); + + verifyLocalBuildLog(JavaS2IBuild.MAVEN_ARGS_APPEND, JavaS2IBuild.MAVEN_ARGS_APPEND.getBuildDefinition() + .getEnvProperties() + .get("MAVEN_ARGS_APPEND")); + } + + @Test + public void mavenClearRepoTest() { + deploy(JavaS2IBuild.MAVEN_CLEAR_REPO.getManagedBuild()); + Assertions.assertThat(openshift.podShell(APP_NAME).execute("sh", "-c", "ls /tmp/artifacts/m2").getOutput()) + .isEmpty(); + } + + @Test + public void absolutePathArtifactDirTest() throws IOException { + // Because of some environment variable changes + if ( OpenJDKTestConfig.isRHEL9()) { + boolean buildResult = startLocalBuild(JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR_NEW.getBuildDefinition().getBuildName(), + JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR_NEW.getBuildDefinition().getEnvProperties()); + String buildName = JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR_NEW.getBuildDefinition().getBuildName(); + LOGGER.info("*********" + buildName + "****************"); + Assertions.assertThat(buildResult).as("Build should fail on absolute path error").isFalse(); + verifyLocalBuildLog(JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR_NEW,"ERROR Absolute path found in MAVEN_S2I_ARTIFACT_DIRS: /target"); + }else { // UBI 8 or RHEL 7 + boolean buildResult = startLocalBuild(JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR.getBuildDefinition().getBuildName(), + JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR.getBuildDefinition().getEnvProperties()); + String buildName = JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR.getBuildDefinition().getBuildName(); + LOGGER.info("*********" + buildName + "****************"); + Assertions.assertThat(buildResult).as("Build should fail on absolute path error").isFalse(); + verifyLocalBuildLog(JavaS2IBuild.ABSOLUTE_PATH_ARTIFACT_DIR,"ERROR Absolute path found in MAVEN_S2I_ARTIFACT_DIRS: /target"); + } + } + + @Test + public void javaOptionsTest() { + deploy(JavaS2IBuild.JAVA_OPTIONS.getManagedBuild()); + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce(JavaS2IBuild.JAVA_OPTIONS.getBuildDefinition() + .getEnvProperties() + .get("JAVA_OPTS")); + } + + @Test + public void javaArgsTest() { + deploy(JavaS2IBuild.JAVA_ARGS.getManagedBuild()); + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce(JavaS2IBuild.JAVA_ARGS.getBuildDefinition() + .getEnvProperties() + .get("JAVA_ARGS")); + } + + @Test + public void javaAppNameTest() { + deploy(JavaS2IBuild.JAVA_APP_NAME.getManagedBuild()); + final String appName = JavaS2IBuild.JAVA_APP_NAME.getBuildDefinition() + .getEnvProperties() + .get("JAVA_APP_NAME"); + if (OpenJDKTestConfig.isRHEL7()){ //rhel 7 containers exhibit a strange parsing where the single quotes remain in the string. + try { + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("'" + appName + "'" ); // "my-app" + } catch (AssertionError ae) { + if (ae.getMessage().contains("but some elements were not found:\n" + + " <[\"" + appName + "\"]>") + && getJavaOpts().contains("'" + appName + "'")) { // "'my-app'" + throw new AssertionError("Old issue: " + ae.getMessage()); + } + throw ae; + } + } else { + try { + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce(appName ); // "my-app" + } catch (AssertionError ae) { + if (ae.getMessage().contains("but some elements were not found:\n" + + " <[\"" + appName + "\"]>") + && getJavaOpts().contains(appName)) { // "'my-app'" + throw new AssertionError("CLOUD-2810 " + ae.getMessage()); + } + throw ae; + } + } + + } + + @Test + @DisabledIf("customConditionalFunction") + public void javaAppDirNameTest() { + deploy(JavaS2IBuild.JAVA_APP_DIR_NAME.getManagedBuild()); + final String appDirName = JavaS2IBuild.JAVA_APP_DIR_NAME.getBuildDefinition() + .getEnvProperties() + .get("JAVA_APP_DIR"); + try { + Assertions.assertThat(getPodEnv()) + .containsOnlyOnce("JAVA_APP_DIR=" + appDirName ); + } catch (AssertionError ae) { + if (ae.getMessage().contains("but some elements were not found:\n" + + " <[\"" + appDirName + "\"]>") + && getJavaOpts().contains(appDirName)) { // "'my-app'" + throw new AssertionError("JAVA_APP_DIR " + ae.getMessage()); + } + throw ae; + } + } + + @Test + public void javaRegularJarTest() { + deploy(JavaS2IBuild.JAVA_REGULAR_JAR_WITH_CLASSPATH_FILE.getManagedBuild()); + String javaLibDir = String.format(":%s/", + JavaS2IBuild.JAVA_REGULAR_JAR_WITH_CLASSPATH_FILE.getBuildDefinition() + .getEnvProperties() + .get("JAVA_LIB_DIR")); // ":lib/" + LOGGER.info("*********" + javaLibDir + "****************"); + + Assertions.assertThat(getJavaOpts()).haveAtLeastOne( + new Condition<>(x -> x + .matches(".*(" + javaLibDir + ").*"), "Has to contain jars in lib dir.")); + } + + @Test + public void javaClassPathTest() { + /*-cp jvm option is ignored in container as -jar opt has precedence, thus we only test presence + //of the JAVA_CLASS_PATH value*/ + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), Collections.singletonMap("JAVA_CLASSPATH", "test.jar")); + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("test.jar"); + } + + @Test + public void javaDiagnosticsTest() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), Collections.singletonMap("JAVA_DIAGNOSTICS", "true")); + if (OpenJDKTestConfig.isOpenJDK17()) { + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("-XX:NativeMemoryTracking=summary") + .containsOnlyOnce("-Xlog:gc::utctime"); + } else if (OpenJDKTestConfig.isOpenJDK11()) { // CLOUD-3040 + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("-XX:NativeMemoryTracking=summary") + .containsOnlyOnce("-Xlog:gc::utctime"); + } else { + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("-XX:NativeMemoryTracking=summary") + .containsOnlyOnce("-XX:+PrintGCDetails") + .containsOnlyOnce("-XX:+PrintGCDateStamps") + .containsOnlyOnce("-XX:+PrintGCTimeStamps") + .containsOnlyOnce("-XX:+UnlockDiagnosticVMOptions"); + } + } + + /** + * + * Spawn a build in a current testing namespace rather than relying on BuildManager. + * This method should ensure build pod logs are accessible for further test assertions. + * + */ + private boolean startLocalBuild(String buildName, Map envVars) throws IOException { + ApplicationBuilder appBuilder = appFromBinaryBuild(buildName); + envVars.forEach( (k,v) -> appBuilder.buildConfig().sti().addEnvVariable(k, v)); + appBuilder.buildApplication(openshift).deploy(); + + Path appPath = prepareProjectSources(buildName, findApplicationDirectory("docker-image-test-app", "springboot")); + startBinaryBuild(appBuilder.buildConfig().getName(), appPath); + + return openshift.waiters().hasBuildCompleted(buildName).waitFor(); + } + + private void verifyLocalBuildLog(final JavaS2IBuild build, final String contain) { + Assertions.assertThat(openshift.builds().withName( + String.format("%s-%s", build.getManagedBuild().getId(), + openshift.buildConfigs().withName(build.getManagedBuild().getId()).get().getStatus().getLastVersion())).getLog()) + .contains(contain); + } + private boolean customConditionalFunction() { + LOGGER.info("Check if running Rhel 7 images."); + return OpenJDKTestConfig.isRHEL7(); + } +} + diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/opts/JavaMemoryOptionsTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/opts/JavaMemoryOptionsTest.java new file mode 100644 index 0000000..f784bb1 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/opts/JavaMemoryOptionsTest.java @@ -0,0 +1,151 @@ +package com.redhat.qe.openjdk.opts; + +import com.redhat.qe.openjdk.OpenJDKTestConfig; +import org.junit.jupiter.api.Test; + +import org.assertj.core.api.Assertions; +import org.assertj.core.api.Condition; + +import com.google.common.collect.ImmutableMap; +import com.redhat.qe.openjdk.common.AbstractEnvVarsTest; +import com.redhat.qe.openjdk.util.annotation.SmokeTest; +import com.redhat.qe.openjdk.util.build.JavaS2IBuild; +import com.redhat.qe.openjdk.util.annotation.JavaS2IProfile; +import com.redhat.qe.openjdk.util.annotation.MultiArchProfile; +import com.redhat.qe.openjdk.util.build.UsesJavaS2IBuild; + +import java.util.Collections; + +import cz.xtf.builder.builders.limits.CPUResource; +import cz.xtf.builder.builders.limits.ComputingResource; +import cz.xtf.builder.builders.limits.MemoryResource; +import cz.xtf.core.http.Https; +import cz.xtf.junit5.annotations.SinceVersion; + +@JavaS2IProfile +@MultiArchProfile +@SmokeTest +@UsesJavaS2IBuild(JavaS2IBuild.DOCKER_IMAGE_TEST_APP) +public class JavaMemoryOptionsTest extends AbstractEnvVarsTest { + + private static final Condition isXmx = new Condition<>(x -> x.contains("-Xmx") ,"-Xmx"); + private static final Condition isXms = new Condition<>(x -> x.contains("-Xms") ,"-Xms"); + + @Test + public void javaMaxMemoryRatioTest() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), + ImmutableMap.of("JAVA_MAX_MEM_RATIO", "25.0"), createCpuResource("100m", "2"), + createMemoryResource("1024Mi", "1024Mi")); + if (OpenJDKTestConfig.isRHEL7()) { + Assertions.assertThat(getJavaOpts()).containsOnlyOnce("-Xmx256m"); + } else { + Assertions.assertThat(getJavaOpts()).containsOnlyOnce("-XX:MaxRAMPercentage=25.0") + .doNotHave(isXmx); + } + } + + @Test + public void javaNativeContainerLimitsTest() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), + ImmutableMap.builder() + // This makes the script to not set explicit mx/ms + .put("JAVA_MAX_MEM_RATIO", "0") + .put("JAVA_INITIAL_MEM_RATIO", "0").build(), + createCpuResource("100m", "2"), + createMemoryResource("1024Mi", "1024Mi")); + + Assertions.assertThat(getJavaOpts()) + .doNotHave(isXmx) + .doNotHave(isXms); + + int availableProcessors = Integer.parseInt(Https.getContent("http://" + openshift.generateHostname(APP_NAME) + "/availableProcessors")); + long maxMemory = Long.parseLong(Https.getContent("http://" + openshift.generateHostname(APP_NAME) + "/maxMemory")); + + Assertions.assertThat(availableProcessors).as("availableProcessors").isEqualTo(2); + Assertions.assertThat(maxMemory).as("maxMemory").isLessThanOrEqualTo(1024 * 1024 * 1024 / 4); // we expect to be less or equal the quarter of the pod memory + } + + + @Test + public void containerMaxMemoryTest() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), + ImmutableMap.of("CONTAINER_MAX_MEMORY", "536870912"), createCpuResource("100m", "2"), + null); + if ( OpenJDKTestConfig.isRHEL9()) { + Assertions.assertThat(getJavaOpts()).containsOnlyOnce("-XX:MaxRAMPercentage=80.0"); + } else if (OpenJDKTestConfig.isRHEL8()) { + // Only set the MaxRAMPercentage to 50. This will be raised to 80 later this year. + Assertions.assertThat(getJavaOpts()).containsOnlyOnce("-XX:MaxRAMPercentage=80.0"); + Assertions.assertThat(getJavaOpts()).doesNotContain("-Xmx256m"); + } else { //Rhel 7 + Assertions.assertThat(getJavaOpts()).containsOnlyOnce("-Xmx256m"); + } + } + + @Test + public void gcOptionsTest() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), + ImmutableMap.builder().put("GC_MIN_HEAP_FREE_RATIO", "30") + .put("GC_MAX_HEAP_FREE_RATIO", "50") + .put("GC_TIME_RATIO", "5") + .put("GC_ADAPTIVE_SIZE_POLICY_WEIGHT", "80") + .put("GC_MAX_METASPACE_SIZE", "95") + .build(), null, null); + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("-XX:+UseParallelGC") + .containsOnlyOnce("-XX:MinHeapFreeRatio=30") + .containsOnlyOnce("-XX:MaxHeapFreeRatio=50") + .containsOnlyOnce("-XX:GCTimeRatio=5") + .containsOnlyOnce("-XX:AdaptiveSizePolicyWeight=80") + .containsOnlyOnce("-XX:MaxMetaspaceSize=95m"); + } + + @Test + public void gcOptionsCustomTest() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), + ImmutableMap.builder() + .put("GC_CONTAINER_OPTIONS", "-XX:+UseG1GC -XX:MinHeapFreeRatio=30") + .build(), null, null); + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("-XX:+UseG1GC") + .containsOnlyOnce("-XX:MinHeapFreeRatio=30") + .doesNotContain("-XX:+UseG1GC -XX:MinHeapFreeRatio=30"); + } + + @Test + public void javaOptsAppendTest() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), + ImmutableMap.builder() + .put("JAVA_OPTS_APPEND", "-XX:GCTimeRatio=5 -XX:MinHeapFreeRatio=20") + .build(), null, null); + Assertions.assertThat(getJavaOpts()) + .containsOnlyOnce("-XX:GCTimeRatio=5") + .containsOnlyOnce("-XX:MinHeapFreeRatio=20") + .doesNotContain("-XX:GCTimeRatio=5 -XX:MinHeapFreeRatio=20"); + } + + private ComputingResource createMemoryResource(final String requests, final String limits) { + final ComputingResource resource = new MemoryResource(); + resource.setRequests(requests); + resource.setLimits(limits); + return resource; + } + + private ComputingResource createCpuResource(final String requests, final String limits) { + final ComputingResource resource = new CPUResource(); + resource.setRequests(requests); + resource.setLimits(limits); + return resource; + } + + @Test + public void testDefaultMaxHeapSettings() { + deploy(JavaS2IBuild.DOCKER_IMAGE_TEST_APP.getManagedBuild(), + Collections.emptyMap(), + null, + null); + Assertions.assertThat(getJavaOpts()) + .doNotHave(isXms) + .doNotHave(isXmx); + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/s2i/AbstractBuildTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/s2i/AbstractBuildTest.java new file mode 100644 index 0000000..51c1b99 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/s2i/AbstractBuildTest.java @@ -0,0 +1,160 @@ +package com.redhat.qe.openjdk.s2i; + +import com.redhat.qe.openjdk.OpenJDKTestParent; +import org.apache.commons.io.FileUtils; +import org.apache.maven.shared.invoker.DefaultInvocationRequest; +import org.apache.maven.shared.invoker.DefaultInvoker; +import org.apache.maven.shared.invoker.InvocationRequest; +import org.apache.maven.shared.invoker.InvocationResult; +import org.apache.maven.shared.invoker.Invoker; +import org.apache.maven.shared.invoker.MavenInvocationException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.assertj.core.api.Assertions; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +import cz.xtf.builder.builders.ApplicationBuilder; +import cz.xtf.client.Http; +import cz.xtf.core.openshift.OpenShift; +import cz.xtf.core.openshift.OpenShifts; +import cz.xtf.core.waiting.WaiterException; +import io.fabric8.openshift.api.model.Build; + +public abstract class AbstractBuildTest extends OpenJDKTestParent { + protected static String appName; + protected static String appModule; + private static final OpenShift openShift = OpenShifts.master(); + private Path preparedSources; + private ApplicationBuilder builder; + + private void setupBuildEnv(Path preparedSources, String mavenArgsAppend, boolean clearRepo) throws IOException { + StringBuilder sb = new StringBuilder(); + if (mavenArgsAppend != null) { + sb.append("MAVEN_ARGS_APPEND=").append(mavenArgsAppend).append("\n"); + } + if (clearRepo) { + sb.append("MAVEN_CLEAR_REPO=true\n"); + } + Files.createDirectories(preparedSources.resolve(".s2i")); + FileUtils.writeStringToFile(preparedSources.resolve(".s2i").resolve("environment").toFile(), sb.toString(), "UTF-8"); + } + + @BeforeEach + public void prepareBuild() throws IOException { + openShift.clean().waitFor(); + Path originalSources = findApplicationDirectory(appName, appModule); + preparedSources = prepareProjectSources(appName, originalSources); + builder = OpenJDKTestParent.appFromBinaryBuild(appName); + } + + @Test + public void binaryBuildFromDir() throws IOException { + builder.buildApplication(openShift).deploy(); + + Build build = OpenJDKTestParent.startBinaryBuild(appName, preparedSources); + openShift.waiters().hasBuildCompleted(build).waitFor(); + Build buildResult = openShift.getBuild(build.getMetadata().getName()); + Assertions.assertThat(buildResult.getStatus().getPhase()).isEqualTo("Complete"); + } + + @Test + public void incrementalRebuild() throws IOException { + builder.buildConfig().sti().incremental(); + builder.buildApplication(openShift).deploy(); + // first build should succeed + Build build = OpenJDKTestParent.startBinaryBuild(appName, preparedSources); + openShift.waiters().hasBuildCompleted(build).waitFor(); + Build buildResult = openShift.getBuild(build.getMetadata().getName()); + Assertions.assertThat(buildResult.getStatus().getPhase()).isEqualTo("Complete"); + + // an subsequent offline incremental build should succeed (with no downloads needed) + setupBuildEnv(preparedSources, "-o", true); + + build = OpenJDKTestParent.startBinaryBuild(appName, preparedSources); + openShift.waiters().hasBuildCompleted(build).waitFor(); + buildResult = openShift.getBuild(build.getMetadata().getName()); + Assertions.assertThat(buildResult.getStatus().getPhase()).isEqualTo("Complete"); + Assertions.assertThat(openShift.getBuildLog(buildResult)).as("No downloads from Internet").doesNotContainPattern(Pattern.compile("(Downloading|Downloaded)")); + + // with repo cleaned, the subsequent offline build should fail + build = OpenJDKTestParent.startBinaryBuild(appName, preparedSources); + openShift.waiters().hasBuildCompleted(build).waitFor(); + buildResult = openShift.getBuild(build.getMetadata().getName()); + Assertions.assertThat(buildResult.getStatus().getPhase()).isEqualTo("Failed"); + Assertions.assertThat(openShift.getBuildLog(buildResult)).as("Build log should contain").contains("[ERROR]"); + Assertions.assertThat(openShift.getBuildLog(buildResult)).as("Build log should contain").contains("Non-resolvable import"); + + // a subsequent on-line build should work + setupBuildEnv(preparedSources, null, true); + + build = OpenJDKTestParent.startBinaryBuild(appName, preparedSources); + openShift.waiters().hasBuildCompleted(build).waitFor(); + buildResult = openShift.getBuild(build.getMetadata().getName()); + Assertions.assertThat(buildResult.getStatus().getPhase()).isEqualTo("Complete"); + Assertions.assertThat(openShift.getBuildLog(buildResult)).as("It should download from Internet").containsPattern(Pattern.compile("(Downloading|Downloaded)")); + } + + @Test + public void failedUnitTestBuild() throws IOException { + builder.buildApplication(openShift).deploy(); + setupBuildEnv(preparedSources, "-P compile-error --threads 1", true); + + Build build = OpenJDKTestParent.startBinaryBuild(appName, preparedSources); + openShift.waiters().hasBuildCompleted(build).waitFor(); + Build buildResult = openShift.getBuild(build.getMetadata().getName()); + Assertions.assertThat(buildResult.getStatus().getPhase()).isEqualTo("Failed"); + Assertions.assertThat(openShift.getBuildLog(buildResult)).as("Build log should contain") + .contains("BUILD FAILURE", "missing return statement"); + } + + @Test + public void binaryBuildFromFile() throws IOException { + Assertions.assertThat(System.getenv("MAVEN_HOME")).as("${MAVEN_HOME} or -Dmaven.home is required").isNotNull(); + + builder.deploymentConfig().podTemplate().container().addReadinessProbe().createHttpProbe("/ping", "8080").setInitialDelaySeconds(30); + builder.service().port("http", 8080); + builder.route(); + if (appModule.equals("wildfly-swarm")) { + builder.deploymentConfig().podTemplate().container().envVar("AB_JOLOKIA_OFF", "true"); + } + builder.buildApplication(openShift).deploy(); + + InvocationRequest mvnRequest = new DefaultInvocationRequest(); + mvnRequest.setBatchMode(true); + mvnRequest.setBaseDirectory(preparedSources.toFile()); + mvnRequest.setUserSettingsFile(findProjectRoot().resolve("settings.xml").toFile()); + mvnRequest.setGoals(Arrays.asList("clean", "package", "-D skipTests")); + + Invoker mvnInvoker = new DefaultInvoker(); + mvnInvoker.setMavenHome(Paths.get(System.getenv("MAVEN_HOME")).toFile()); + try { + InvocationResult mvnResult = mvnInvoker.execute(mvnRequest); + Assertions.assertThat(mvnResult.getExitCode()).isEqualTo(0); + } catch (MavenInvocationException e) { + e.printStackTrace(); + Assertions.fail("Local Maven build failed", e); + } + String fileName = appName + (appModule.equals("springboot") ? "" : "-thorntail") + ".jar"; + openShift.buildConfigs().withName(appName).instantiateBinary().asFile(fileName).fromFile(preparedSources.resolve("target/" + fileName).toFile()); + openShift.waiters().hasBuildCompleted(appName).waitFor(); + Build buildResult = openShift.getBuild(openShift.getLatestBuild(appName).getMetadata().getName()); + Assertions.assertThat(buildResult.getStatus().getPhase()).isEqualTo("Complete"); + + try { + openShift.waiters().isDcReady(appName).timeout(TimeUnit.MINUTES, 3).waitFor(); + Http.get("http://" + openShift.generateHostname(appName) + "/ping").waiters().ok().timeout(TimeUnit.MINUTES, 2).waitFor(); + } catch (WaiterException e) { + Assertions.fail("CLOUD-3095: application haven't started in time", e); + } + } + +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/s2i/springboot/SpringBootBuildTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/s2i/springboot/SpringBootBuildTest.java new file mode 100644 index 0000000..7d83b35 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/s2i/springboot/SpringBootBuildTest.java @@ -0,0 +1,18 @@ +package com.redhat.qe.openjdk.s2i.springboot; + +import com.redhat.qe.openjdk.s2i.AbstractBuildTest; +import com.redhat.qe.openjdk.util.annotation.MultiArchProfile; +import com.redhat.qe.openjdk.util.annotation.SmokeTest; +import org.junit.jupiter.api.BeforeAll; + +@SmokeTest +@MultiArchProfile +public class SpringBootBuildTest extends AbstractBuildTest { + + @BeforeAll + public static void init() { + appName = "sti"; + appModule = "springboot"; + } + +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/AbstractServerDeployment.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/AbstractServerDeployment.java new file mode 100644 index 0000000..2c81d5d --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/AbstractServerDeployment.java @@ -0,0 +1,126 @@ +package com.redhat.qe.openjdk.util; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeoutException; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import cz.xtf.builder.builders.RouteBuilder; +import cz.xtf.core.openshift.OpenShift; +import cz.xtf.core.openshift.OpenShifts; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.ReplicationController; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.openshift.api.model.DeploymentConfig; + + +public abstract class AbstractServerDeployment { + private static final int DEFAULT_WAIT_TIMEOUT = 180_000; + protected final String name; + protected final String hostName; + protected final String cluster; + protected final String secureHostname; + + protected static final OpenShift openshift = OpenShifts.master(); + + + public AbstractServerDeployment(final String name, final String hostName, final String cluster) { + this(name, hostName, cluster, null); + } + + public AbstractServerDeployment(final String name, final String hostName, final String cluster, + final String secureHostname) { + this.name = name; + this.hostName = hostName; + this.cluster = cluster; + this.secureHostname = secureHostname; + } + + public String getHostName() { + return this.hostName; + } + + public Collection getServices() { + return openshift + .getServices() + .stream() + .filter(getServicePredicate()) + .collect(Collectors.toList()); + } + + public Collection getPods() { + return openshift.getLabeledPods("name", this.name); + } + + public Pod getRandomPod() { + return openshift.getAnyPod("name",this.name); + } + + public ReplicationController getReplicationController() { + final List rcs = openshift + .replicationControllers().list().getItems() + .stream() + .filter(rc -> this.name.equals(rc.getSpec() + .getSelector() + .get("name"))) + .collect(Collectors.toList()); + if (rcs.size() == 0) { + throw new IllegalStateException("No replication controller for name='" + this.name + "' found!"); + } + if (rcs.size() > 1) { + throw new IllegalStateException("More than 1 replication controller for name='" + this.name + "' found!"); + } + return rcs.get(0); + } + + public DeploymentConfig getDeploymentConfig() { + return openshift.getDeploymentConfig(this.name); + } + + public Predicate getPodPredicate() { + return p -> this.name.equals(p.getMetadata() + .getLabels() + .get("name")); + } + + public Predicate getServicePredicate() { + return s -> this.name.equals(s.getSpec() + .getSelector() + .get("name")); + } + + // Convenience methods + public void scale(final int replicas) { + openshift.scale(this.name, replicas); + } + + public void scaleAndWait(final int replicas) throws TimeoutException, InterruptedException { + scaleAndWait(replicas, DEFAULT_WAIT_TIMEOUT); + } + + public void scaleAndWait(final int replicas, + final long timeoutInMillis) throws TimeoutException, InterruptedException { + scale(replicas); + + if (replicas == 0) { + openshift.waiters().areNoPodsPresent(this.name).waitFor(); + } else { + openshift.waiters().areExactlyNPodsReady(replicas, this.name).waitFor(); + } + } + + public void removeRoute() { + openshift.routes().withName(this.name + "-route").delete(); + } + + public void redirectRouteToOtherDeployment(final AbstractServerDeployment other) { + openshift.createRoute(new RouteBuilder(this.name + "-route").forService(other.name + "-service") + .exposedAsHost(this.getHostName()) + .build()); + } + + public String getSecureHostname() { + return this.secureHostname; + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/ProcessKeystoreGenerator.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/ProcessKeystoreGenerator.java new file mode 100644 index 0000000..0f6fdf4 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/ProcessKeystoreGenerator.java @@ -0,0 +1,179 @@ +package com.redhat.qe.openjdk.util; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import cz.xtf.core.openshift.OpenShifts; +import lombok.Getter; + +/** + * Class for generating keystores signed by one common generated ca + */ +public class ProcessKeystoreGenerator { + + private static Path TMP_DIRECTORY = Paths.get("tmp").toAbsolutePath().resolve("keystores"); + + @Getter + private static Path caDir; + + @Getter + private static Path truststore; + + static { + try { + TMP_DIRECTORY.toFile().mkdirs(); + caDir = Files.createTempDirectory(TMP_DIRECTORY, "ca"); + + // Generate key and cert + processCall(caDir, "openssl", "req", "-new", "-newkey", "rsa:4096", "-x509", "-keyout", "ca-key.pem", "-out", "ca-certificate.pem", "-days", "365", "-passout", "pass:password", "-subj", "/C=CZ/ST=CZ/L=Brno/O=QE/CN=xtf.ca"); + + // Generate truststore with ca cert + processCall(caDir, "keytool", "-import", "-noprompt", "-keystore", "truststore", "-file", "ca-certificate.pem", "-alias", "xtf.ca", "-storepass", "password"); + + // Import openshift server certs to truststore + URL ocpApiUrl = OpenShifts.master().getOpenshiftUrl(); + String server = ocpApiUrl.getHost() + ":" + ocpApiUrl.getPort(); + + processCall(caDir, "/bin/sh", "-c", "echo \"Q\" | openssl s_client -connect " + server + " -showcerts 2>/dev/null > serversOpenSslResponse"); + String splitCmd = System.getProperty("os.name").toLowerCase().startsWith("mac") ? "gcsplit" : "csplit"; + processCall(caDir, "/bin/sh", "-c", splitCmd + " -f serverCert -s serversOpenSslResponse '/^-----BEGIN CERTIFICATE-----$/' '{*}'"); + + processCall(caDir, "/bin/sh", "-c", "find . -type f -not -name \"serverCert00\" -name \"serverCert[0-9][0-9]\" -exec openssl x509 -in {} -out {}.pem \\;"); + processCall(caDir, "/bin/sh", "-c", "find . -type f -name \"serverCert[0-9][0-9].pem\" -exec keytool -import -noprompt -keystore truststore -file {} -alias {} -storepass password \\;"); + + truststore = caDir.resolve("truststore"); + } catch (IOException e) { + throw new IllegalStateException("Failed to initialize ca", e); + } + } + + public static Path generateKeystore(String hostname) { + return generateKeystore(hostname, null, hostname, false); + } + + public static Path generateKeystore(String hostname, String keyAlias) { + return generateKeystore(hostname, null, keyAlias, false); + } + + public static Path generateKeystore(String hostname, String keyAlias, boolean deleteCaFromKeyStore) { + return generateKeystore(hostname, null, keyAlias, deleteCaFromKeyStore); + } + + public static Path generateKeystore(String hostname, String[] alternativeHostnames) { + return generateKeystore(hostname, alternativeHostnames, hostname, false); + } + + public static Path generateKeystore(String hostname, String[] alternativeHostnames, String keyAlias, boolean deleteCaFromKeyStore) { + String keystore = hostname + ".keystore"; + + if (caDir.resolve(keystore).toFile().exists()) { + return caDir.resolve(keystore); + } + + processCall(caDir, "keytool", "-genkeypair", "-keyalg", "RSA", "-noprompt", "-alias", keyAlias, "-dname", "CN=" + hostname + ", OU=TF, O=XTF, L=Brno, S=CZ, C=CZ", "-keystore", keystore, "-storepass", "password", "-keypass", "password", "-deststoretype", "pkcs12"); + + processCall(caDir, "keytool", "-keystore", keystore, "-certreq", "-alias", keyAlias, "--keyalg", "rsa", "-file", hostname + ".csr", "-storepass", "password"); + + if (alternativeHostnames != null && alternativeHostnames.length > 0) { + try { + Writer writer = new FileWriter(caDir.resolve(keyAlias + ".extensions").toFile()); + writer.write("[ req_ext ]\n"); + writer.write("subjectAltName = @alt_names\n"); + writer.write("\n"); + writer.write("[ alt_names ]\n"); + + writer.write("DNS.1 = " + hostname + "\n"); + for (int i = 0; i < alternativeHostnames.length; ++i) { + writer.write("DNS." + (i + 2) + " = " + alternativeHostnames[i] + "\n"); + } + writer.flush(); + writer.close(); + + processCall(caDir, "openssl", "x509", "-req", "-CA", "ca-certificate.pem", "-CAkey", "ca-key.pem", "-in", hostname + ".csr", "-out", hostname + ".cer", "-days", "365", "-CAcreateserial", "-passin", "pass:password", "-extfile", keyAlias + ".extensions", "-extensions", "req_ext"); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + processCall(caDir, "openssl", "x509", "-req", "-CA", "ca-certificate.pem", "-CAkey", "ca-key.pem", "-in", hostname + ".csr", "-out", hostname + ".cer", "-days", "365", "-CAcreateserial", "-passin", "pass:password"); + } + + processCall(caDir, "keytool", "-import", "-noprompt", "-keystore", keystore, "-file", "ca-certificate.pem", "-alias", "xtf.ca", "-storepass", "password"); + + processCall(caDir, "keytool", "-import", "-keystore", keystore, "-file", hostname + ".cer", "-alias", keyAlias, "-storepass", "password"); + + if (deleteCaFromKeyStore) { + processCall(caDir, "keytool", "-delete", "-noprompt", "-alias", "xtf.ca", "-keystore", keystore, "-storepass", "password"); + } + + return caDir.resolve(keystore); + } + + public static CertPaths generateCerts(String hostname) { + return generateCerts(hostname, null); + } + + public static CertPaths generateCerts(String hostname, String[] alternativeHostnames) { + String keystore = hostname + ".keystore"; + + generateKeystore(hostname, alternativeHostnames); + + // export cert as CN.keystore.pem + processCall(caDir, "keytool", "-exportcert", "-rfc", "-keystore", keystore, "-alias", hostname, "-storepass", "password", "-file", keystore + ".pem"); + + // convert to CN.keystore.keywithattrs.pem + processCall(caDir, "openssl", "pkcs12", "-in", keystore, "-nodes", "-nocerts", "-out", keystore + ".keywithattrs.pem", "-passin", "pass:password"); + + // Remove the Bag attributes to CN.keystore.key.pem + processCall(caDir, "openssl", "rsa", "-in", keystore + ".keywithattrs.pem", "-out", keystore + ".key.pem"); + + return new CertPaths( + caDir.resolve("ca-certificate.pem"), + caDir.resolve("truststore"), + caDir.resolve(keystore), + caDir.resolve(keystore + ".key.pem"), + caDir.resolve(keystore + ".pem")); + } + + private static void processCall(Path cwd, String... args) { + ProcessBuilder pb = new ProcessBuilder(args); + + pb.directory(cwd.toFile()); + pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + + int result = -1; + + try { + result = pb.start().waitFor(); + } catch (IOException | InterruptedException e) { + throw new IllegalStateException("Failed executing " + String.join(" ", args)); + } + + if (result != 0) { + throw new IllegalStateException("Failed executing " + String.join(" ", args)); + } + } + + public static class CertPaths { + + public CertPaths(Path caPem, Path truststore, Path keystore, Path keyPem, Path certPem) { + this.caPem = caPem; + this.truststore = truststore; + this.keystore = keystore; + this.keyPem = keyPem; + this.certPem = certPem; + } + + public Path caPem; + public Path truststore; + public Path keystore; + public Path keyPem; + public Path certPem; + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/RandomUtil.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/RandomUtil.java new file mode 100644 index 0000000..5111344 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/RandomUtil.java @@ -0,0 +1,17 @@ +package com.redhat.qe.openjdk.util; + +import java.util.Random; + +public class RandomUtil { + public static String generateUniqueId(final String name, final String separator) { + return name + separator + Integer.toString(Math.abs(new Random().nextInt()), 36); + } + + public static String generateUniqueId(final String name) { + return generateUniqueId(name, "-"); + } + + public static String generateUniqueId() { + return generateUniqueId("", ""); + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/Tuple.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/Tuple.java new file mode 100644 index 0000000..d55ad6e --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/Tuple.java @@ -0,0 +1,105 @@ +package com.redhat.qe.openjdk.util; + +import java.io.Serializable; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; + +public class Tuple { + public static interface Pair extends Serializable { + public X getFirst(); + + public Y getSecond(); + } + + public static interface Triple extends Serializable { + public X getFirst(); + + public Y getSecond(); + + public Z getThird(); + } + + public static class PairImpl implements Pair { + private static final long serialVersionUID = -114609472475893593L; + private X first; + private Y second; + + public PairImpl(X x, Y y) { + this.first = x; + this.second = y; + } + + public X getFirst() { + return first; + } + + public Y getSecond() { + return second; + } + + @Override + public String toString() { + return "(" + first + ", " + second + ")"; + } + } + + public static Pair pair(X x, Y y) { + return new PairImpl(x, y); + } + + public static Function, Pair> pairBinarizeFirst(BiFunction func) { + return (Pair p) -> { + W w = func.apply(p.getFirst(), p.getSecond()); + return pair(p.getFirst(), w); + }; + } + + public static Function, Pair> pairIgnoreFirst(Function func) { + return (Pair p) -> { + W w = func.apply(p.getSecond()); + return pair(p.getFirst(), w); + }; + } + + public static Function, Pair> pairConsumeSecond(Consumer func) { + return (Pair p) -> { + func.accept(p.getSecond()); + return p; + }; + } + + public static Triple triple(X x, Y y, Z z) { + return new TripleImpl(x, y, z); + } + + public static class TripleImpl implements Triple { + private static final long serialVersionUID = 4035047312787547257L; + private X first; + private Y second; + private Z third; + + public TripleImpl(X x, Y y, Z z) { + this.first = x; + this.second = y; + this.third = z; + } + + public X getFirst() { + return first; + } + + public Y getSecond() { + return second; + } + + public Z getThird() { + return third; + } + + @Override + public String toString() { + return "(" + first + ", " + second + ", " + third + ")"; + } + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/JavaS2IProfile.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/JavaS2IProfile.java new file mode 100644 index 0000000..5da75af --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/JavaS2IProfile.java @@ -0,0 +1,16 @@ +package com.redhat.qe.openjdk.util.annotation; + + +import org.junit.jupiter.api.Tag; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + */ +@Tag("javas2i") +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.TYPE}) +public @interface JavaS2IProfile { +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/MultiArchProfile.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/MultiArchProfile.java new file mode 100644 index 0000000..fcb3418 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/MultiArchProfile.java @@ -0,0 +1,14 @@ +package com.redhat.qe.openjdk.util.annotation; + + +import org.junit.jupiter.api.Tag; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Tag("multiarch") +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.TYPE}) +public @interface MultiArchProfile { +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/SmokeTest.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/SmokeTest.java new file mode 100644 index 0000000..f990d7b --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/annotation/SmokeTest.java @@ -0,0 +1,14 @@ +package com.redhat.qe.openjdk.util.annotation; + + +import org.junit.jupiter.api.Tag; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Tag("smoke") +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.TYPE}) +public @interface SmokeTest { +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/JavaS2IBuild.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/JavaS2IBuild.java new file mode 100644 index 0000000..cd01671 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/JavaS2IBuild.java @@ -0,0 +1,103 @@ +package com.redhat.qe.openjdk.util.build; + +import com.google.common.collect.ImmutableMap; + +import com.redhat.qe.openjdk.OpenJDKTestConfig; + +import cz.xtf.core.bm.BinaryBuild; +import cz.xtf.junit5.interfaces.BuildDefinition; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * These builds use Spring Boot, but Spring Boot isn't actually subject of the respective tests. + * It is only used to create a meaningful deployment. No other variants (Vert.x, WildFly Swarm) are necessary. + * + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@AllArgsConstructor +public enum JavaS2IBuild implements BuildDefinition { + DOCKER_IMAGE_TEST_APP(new SpringBootBuildDefinition("docker-image-test-app")), + MAVEN_ARGS( + new SpringBootBuildDefinition("docker-image-test-app", "maven-args", + ImmutableMap.of( + "MAVEN_ARGS", "clean validate package -Dcom.redhat.qe.openjdk.repo.redhatga"))), + MAVEN_ARGS_APPEND( + new SpringBootBuildDefinition("docker-image-test-app", "maven-args-append", + ImmutableMap.of( + "MAVEN_ARGS_APPEND", "-Dmy.property=hello"))), + MAVEN_CLEAR_REPO( + new SpringBootBuildDefinition("docker-image-test-app", "maven-clear-repo", + ImmutableMap.of( + "MAVEN_CLEAR_REPO", "true"))), + JAVA_OPTIONS( + new SpringBootBuildDefinition("docker-image-test-app", "java-options", + ImmutableMap.of( + "JAVA_OPTS", "-Dhttp.nonProxyHosts=example.com"))), + JAVA_ARGS( + new SpringBootBuildDefinition("docker-image-test-app", "java-args", + ImmutableMap.of( + "JAVA_ARGS", "hello-world"))), + JAVA_APP_NAME( + new SpringBootBuildDefinition("docker-image-test-app", "java-app-name", + ImmutableMap.of( + "JAVA_APP_NAME", "my-app"))), + + JAVA_APP_DIR_NAME(getSpringBootBuildDefinition()), + JAVA_REGULAR_JAR_WITH_CLASSPATH_FILE( + new SpringBootBuildDefinition("docker-image-test-app", "java-regular-jar-with-classpath-file", + ImmutableMap.builder() + .put("JAVA_MAIN_CLASS", "com.redhat.qe.openjdk.springboot.tomcat.SampleTomcatApplication") + .put("MAVEN_S2I_GOALS", "clean package -P regular-jar") + .put("S2I_SOURCE_DEPLOYMENTS_FILTER", "-r lib *.jar") + .put("JAVA_LIB_DIR", "lib") + .put("JAVA_APP_JAR", "docker-image-test-app.jar") + .put("JAVA_APP_DIR", "/deployments") + .put("MAVEN_CLEAR_REPO", "true") + .build())), + NON_EXISTING_ARTIFACT_DIR( + new SpringBootBuildDefinition("docker-image-test-app", "non-existing-artifact-dir", + ImmutableMap.of( + "ARTIFACT_DIR", "non_existing_dir"))), + ABSOLUTE_PATH_ARTIFACT_DIR( + new SpringBootBuildDefinition("docker-image-test-app", "absolute-path-artifact-dir", + ImmutableMap.of("ARTIFACT_DIR", "/target"))), + ABSOLUTE_PATH_ARTIFACT_DIR_NEW( + new SpringBootBuildDefinition("docker-image-test-app", "absolute-path-artifact-dir", + ImmutableMap.of("MAVEN_S2I_ARTIFACT_DIRS", "/target"))), + HTTP_PROXY_CONF_LOWERCASE_MULTIPLE_HOSTS( + new SpringBootBuildDefinition("docker-image-test-app", "http-proxy-lowercase-multiple-hosts", + ImmutableMap.of( + "no_proxy", ".foo.com,.bar.com"))); + + @Getter + private final SpringBootBuildDefinition buildDefinition; + + @Override + public BinaryBuild getManagedBuild() { + return buildDefinition.getManagedBuild(); + } + + private static SpringBootBuildDefinition getSpringBootBuildDefinition() { + String homeFolderName; + + if (OpenJDKTestConfig.isRHEL9()) { + //Rhel 9s home folder is /home/default + homeFolderName = "/home/default"; + }else { + homeFolderName = "/home/jboss"; + } + + return new SpringBootBuildDefinition("docker-image-test-app", "java-app-dir-name", + ImmutableMap.builder() + .put("JAVA_APP_NAME", "my-app") + .put("JAVA_APP_DIR", homeFolderName) + .put("S2I_TARGET_DEPLOYMENTS_DIR", homeFolderName) + .put("MAVEN_CLEAR_REPO", "true") + .build() + ); + } + + + +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/SpringBootBuild.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/SpringBootBuild.java new file mode 100644 index 0000000..179462f --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/SpringBootBuild.java @@ -0,0 +1,29 @@ +package com.redhat.qe.openjdk.util.build; + + + +import cz.xtf.core.bm.BinaryBuild; +import cz.xtf.junit5.interfaces.BuildDefinition; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@AllArgsConstructor +public enum SpringBootBuild implements BuildDefinition { + + SSL(new SpringBootBuildDefinition("ssl")), + + NOHA_SERVLET_COUNTER(new SpringBootBuildDefinition("noha-servlet-counter")); + + + @Getter + private final SpringBootBuildDefinition buildDefinition; + + @Override + public BinaryBuild getManagedBuild() { + return buildDefinition.getManagedBuild(); + } + +} \ No newline at end of file diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/SpringBootBuildDefinition.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/SpringBootBuildDefinition.java new file mode 100644 index 0000000..773900c --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/SpringBootBuildDefinition.java @@ -0,0 +1,78 @@ +package com.redhat.qe.openjdk.util.build; + +import com.redhat.qe.openjdk.OpenJDKTestConfig; +import com.redhat.qe.openjdk.OpenJDKTestParent; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import cz.xtf.core.bm.BinaryBuild; +import cz.xtf.core.bm.BinarySourceBuild; +import cz.xtf.junit5.interfaces.BuildDefinition; +import lombok.Getter; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@Getter +public class SpringBootBuildDefinition implements BuildDefinition { + + private final static String MODULE_NAME = "springboot"; + + private String buildName; + private Path path; + private Map envProperties; + + private BinarySourceBuild managedBuild = null; + + public SpringBootBuildDefinition(String appName) { + init(appName, OpenJDKTestParent.findApplicationDirectory(appName, MODULE_NAME), null); + } + + public SpringBootBuildDefinition(String appName, String buildName, Map envProperties) { + init(buildName, OpenJDKTestParent.findApplicationDirectory(appName, MODULE_NAME), envProperties); + } + + private void init(String buildName, Path path, Map envProperties) { + this.buildName = buildName; + this.path = path; + this.envProperties = envProperties; + } + + public Map getEnvProperties() { + System.out.println("PRINTOUT THE MAP OF STRINGS."); + for (String key : envProperties.keySet()){ + System.out.println(key + " = " + envProperties.get(key)); + } + System.out.println(); + return envProperties; + } + + @Override + public BinaryBuild getManagedBuild() { + + if (managedBuild == null) { + try { + Path preparedSources = OpenJDKTestParent.prepareProjectSources(buildName, path); + + Map properties = new HashMap<>(); + + if (envProperties != null) { + properties.putAll(envProperties); + } + + if (OpenJDKTestConfig.isMavenProxyEnabled()) { + properties.put("MAVEN_MIRROR_URL", OpenJDKTestConfig.mavenProxyUrl()); + } + + managedBuild = new BinarySourceBuild(OpenJDKTestConfig.imageUrl(), preparedSources, properties, buildName); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return managedBuild; + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesJavaS2IBuild.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesJavaS2IBuild.java new file mode 100644 index 0000000..d4e049a --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesJavaS2IBuild.java @@ -0,0 +1,18 @@ +package com.redhat.qe.openjdk.util.build; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import cz.xtf.junit5.annotations.UsesBuild; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@UsesBuild +public @interface UsesJavaS2IBuild { + JavaS2IBuild value(); +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesJavaS2IBuilds.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesJavaS2IBuilds.java new file mode 100644 index 0000000..7a1eb0c --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesJavaS2IBuilds.java @@ -0,0 +1,18 @@ +package com.redhat.qe.openjdk.util.build; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import cz.xtf.junit5.annotations.UsesBuild; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@UsesBuild +public @interface UsesJavaS2IBuilds { + JavaS2IBuild[] value(); +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesSpringBootBuild.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesSpringBootBuild.java new file mode 100644 index 0000000..ea235d2 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesSpringBootBuild.java @@ -0,0 +1,18 @@ +package com.redhat.qe.openjdk.util.build; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import cz.xtf.junit5.annotations.UsesBuild; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@UsesBuild +public @interface UsesSpringBootBuild { + SpringBootBuild value(); +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesSpringBootBuilds.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesSpringBootBuilds.java new file mode 100644 index 0000000..0f5609c --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesSpringBootBuilds.java @@ -0,0 +1,18 @@ +package com.redhat.qe.openjdk.util.build; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import cz.xtf.junit5.annotations.UsesBuild; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@UsesBuild +public @interface UsesSpringBootBuilds { + SpringBootBuild[] value(); +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesWildFlySwarmBuild.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesWildFlySwarmBuild.java new file mode 100644 index 0000000..02aa369 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesWildFlySwarmBuild.java @@ -0,0 +1,15 @@ +package com.redhat.qe.openjdk.util.build; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import cz.xtf.junit5.annotations.UsesBuild; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@UsesBuild +public @interface UsesWildFlySwarmBuild { + WildFlySwarmBuild value(); +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesWildFlySwarmBuilds.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesWildFlySwarmBuilds.java new file mode 100644 index 0000000..5f5ec0c --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/UsesWildFlySwarmBuilds.java @@ -0,0 +1,15 @@ +package com.redhat.qe.openjdk.util.build; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import cz.xtf.junit5.annotations.UsesBuild; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@UsesBuild +public @interface UsesWildFlySwarmBuilds { + WildFlySwarmBuild[] value(); +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/WildFlySwarmBuild.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/WildFlySwarmBuild.java new file mode 100644 index 0000000..f51f940 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/WildFlySwarmBuild.java @@ -0,0 +1,23 @@ +package com.redhat.qe.openjdk.util.build; + +import java.util.Collections; + +import cz.xtf.core.bm.ManagedBuild; +import cz.xtf.junit5.interfaces.BuildDefinition; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +public enum WildFlySwarmBuild implements BuildDefinition { + + SSL(new WildFlySwarmBuildDefinition("ssl", "wfs-ssl", Collections.emptyMap())), + HELLO_WORLD(new WildFlySwarmBuildDefinition("hello-world")); + + @Getter + private final BuildDefinition buildDefinition; + + @Override + public ManagedBuild getManagedBuild() { + return this.buildDefinition.getManagedBuild(); + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/WildFlySwarmBuildDefinition.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/WildFlySwarmBuildDefinition.java new file mode 100644 index 0000000..c5c65e3 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/build/WildFlySwarmBuildDefinition.java @@ -0,0 +1,63 @@ +package com.redhat.qe.openjdk.util.build; + +import com.redhat.qe.openjdk.OpenJDKTestConfig; +import com.redhat.qe.openjdk.OpenJDKTestParent; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import cz.xtf.core.bm.BinarySourceBuild; +import cz.xtf.core.bm.ManagedBuild; +import cz.xtf.junit5.interfaces.BuildDefinition; + +public class WildFlySwarmBuildDefinition implements BuildDefinition { + private final static String MODULE_NAME = "wildfly-swarm"; + + private String buildName; + private Path path; + private Map envProperties; + + private ManagedBuild managedBuild = null; + + public WildFlySwarmBuildDefinition(String appName) { + init(appName, OpenJDKTestParent.findApplicationDirectory(appName, MODULE_NAME), null); + } + + public WildFlySwarmBuildDefinition(String appName, String buildName, Map envProperties) { + init(buildName, OpenJDKTestParent.findApplicationDirectory(appName, MODULE_NAME), envProperties); + } + + private void init(String buildName, Path path, Map envProperties) { + this.buildName = buildName; + this.path = path; + this.envProperties = envProperties; + } + + @Override + public ManagedBuild getManagedBuild() { + + if (managedBuild == null) { + try { + Path preparedSources = OpenJDKTestParent.prepareProjectSources(buildName, path); + + Map properties = new HashMap<>(); + + if (envProperties != null) { + properties.putAll(envProperties); + } + + if (OpenJDKTestConfig.isMavenProxyEnabled()) { + properties.put("MAVEN_MIRROR_URL", OpenJDKTestConfig.mavenProxyUrl()); + } + + managedBuild = new BinarySourceBuild(OpenJDKTestConfig.imageUrl(), preparedSources, properties, buildName); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return managedBuild; + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/MsaDeploymentBuilder.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/MsaDeploymentBuilder.java new file mode 100644 index 0000000..d5532af --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/MsaDeploymentBuilder.java @@ -0,0 +1,495 @@ +package com.redhat.qe.openjdk.util.deployment; + +import com.redhat.qe.openjdk.util.ProcessKeystoreGenerator; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.FileUtils; + +import org.junit.jupiter.api.Assertions; + +import com.redhat.qe.openjdk.OpenJDKTestConfig; +import com.redhat.qe.openjdk.jolokia.JolokiaConfiguration; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; +import java.util.function.Consumer; + +import cz.xtf.builder.builders.ApplicationBuilder; +import cz.xtf.builder.builders.deployment.AbstractProbe; +import cz.xtf.builder.builders.limits.ComputingResource; +import cz.xtf.builder.builders.pod.ContainerBuilder; +import cz.xtf.builder.builders.pod.PersistentVolumeClaim; +import cz.xtf.builder.db.OpenShiftAuxiliary; +import cz.xtf.client.Http; +import cz.xtf.core.bm.BinaryBuild; +import cz.xtf.core.bm.BuildManagers; +import cz.xtf.core.bm.ManagedBuild; +import cz.xtf.core.config.BuildManagerConfig; +import cz.xtf.core.openshift.OpenShift; +import cz.xtf.core.openshift.OpenShifts; +import io.fabric8.kubernetes.api.model.SecretBuilder; +import lombok.extern.slf4j.Slf4j; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +@Slf4j +public class MsaDeploymentBuilder { + private final String appName; + private int replicas; + private BinaryBuild build; + private final String hostname; + private String urlSuffix; + private final MsaDeploymentType deyplotmentType; + private boolean ssl = false; + private boolean deleteCaFromKeyStore = false; + private String secureHostName; + private String secureUrlSuffix; + private Map deploymentEnvironmentVariables = Collections.emptyMap(); + private boolean generateMirrorSettings = true; + private ComputingResource cpuResource; + private ComputingResource memoryResource; + private JolokiaConfiguration jolokiaConf = new JolokiaConfiguration.Builder().build(); + private String jolokiaHostname; + private Consumer containerModification; + private OpenShiftAuxiliary database; + private boolean dbPostDeployment; + private String dbPostDeploymentName; + private ApplicationBuilder appBuilder; + private AbstractProbe readinessProbe; + private PersistentVolumeClaim persistentVolumeClaim; + private String pvcMountPath; + + public MsaDeploymentBuilder(final String appName, final MsaDeploymentType deploymentType) { + this.appName = appName; + this.replicas = 1; + this.hostname = OpenShifts.master().generateHostname(appName); + this.urlSuffix = null; + this.deyplotmentType = deploymentType; + } + + public static MsaDeploymentBuilder withNewApp(final String appName, final MsaDeploymentType deploymentType) { + return new MsaDeploymentBuilder(appName, deploymentType); + } + + public static MsaDeploymentBuilder withNewSpringBootApp(final String appName) { + return new MsaDeploymentBuilder(appName, MsaDeploymentType.SPRING_BOOT); + } + + public static MsaDeploymentBuilder withNewWildFlySwarmApp(final String appName) { + return new MsaDeploymentBuilder(appName, MsaDeploymentType.WILDFLY_SWARM); + } + + public static MsaDeploymentBuilder withNewJavaS2IApp(final String appName) { + return new MsaDeploymentBuilder(appName, MsaDeploymentType.JAVA_S2I); + } + + public MsaDeploymentBuilder withBuild(final ManagedBuild build) { + this.build = (BinaryBuild) build; + return this; + } + + public MsaDeploymentBuilder replicas(final int replicas) { + this.replicas = replicas; + return this; + } + + public MsaDeploymentBuilder urlCheck(final String urlSuffix) { + this.urlSuffix = urlSuffix; + return this; + } + + public MsaDeploymentBuilder secureUrlCheck(final String secureUrlSuffix) { + this.secureUrlSuffix = secureUrlSuffix; + return this; + } + + public MsaDeploymentBuilder withSsl() { + this.ssl = true; + this.deleteCaFromKeyStore = false; + return this; + } + + public MsaDeploymentBuilder withSsl(boolean deleteCaFromKeyStore) { + this.ssl = true; + this.deleteCaFromKeyStore = deleteCaFromKeyStore; + return this; + } + + public MsaDeploymentBuilder withDatabase(final OpenShiftAuxiliary db, final boolean postDeployment) { + this.database = db; + this.dbPostDeployment = postDeployment; + return this; + } + + public MsaDeploymentBuilder withDeploymentEnvironmentVariables(final Map envVars) { + this.deploymentEnvironmentVariables = envVars; + return this; + } + + public MsaDeploymentBuilder generateMirrorSettings(final boolean generate) { + this.generateMirrorSettings = generate; + return this; + } + + public MsaDeploymentBuilder withCPUResource(final ComputingResource cpuResource) { + this.cpuResource = cpuResource; + return this; + } + + public MsaDeploymentBuilder withMemoryResource(final ComputingResource memoryResource) { + this.memoryResource = memoryResource; + return this; + } + + public MsaDeploymentBuilder configureJolokia(final JolokiaConfiguration jolokiaConf) { + this.jolokiaConf = jolokiaConf; + return this; + } + + public MsaDeploymentBuilder withContainerModification(final Consumer containerModification) { + this.containerModification = containerModification; + return this; + } + + public MsaDeploymentBuilder withReadinessProbe(final AbstractProbe readinessProbe) { + this.readinessProbe = readinessProbe; + return this; + } + + public MsaDeploymentBuilder withPersistentVolumeClaim(PersistentVolumeClaim persistentVolumeClaim, String mountPath) { + this.persistentVolumeClaim = persistentVolumeClaim; + this.pvcMountPath = mountPath; + return this; + } + + private void createMavenProxyConfXml(Path appDirectory) { + File m2SettingsXml = null; + if (OpenJDKTestConfig.isMavenProxyEnabled()) { + // create only if the configuration/settings.xml doesn't exist already + if (!appDirectory.resolve("configuration").toFile().isDirectory()) { + appDirectory.resolve("configuration").toFile().mkdirs(); + } + m2SettingsXml = appDirectory.resolve("configuration").resolve("settings.xml").toFile(); + //clean if exists + if (m2SettingsXml.isFile()) { + m2SettingsXml.delete(); + } + try (FileWriter fw = new FileWriter(m2SettingsXml)) { + fw.write(String.format("\n" + + " \n" + + " \n" + + " s2i-mirror\n" + + " %s\n" + + " external:*\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " springboot-upstream\n" + + " \n" + + " \n" + + " springboot-upstream-repository-snapshots\n" + + " https://repository.jboss.org/nexus/content/repositories/snapshots/\n" + + " \n" + + " true\n" + + " \n" + + " \n" + + " true\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " springboot-upstream-repository-snapshots\n" + + " https://repository.jboss.org/nexus/content/repositories/snapshots/\n" + + " \n" + + " true\n" + + " \n" + + " \n" + + " true\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " springboot-upstream\n" + + " \n" + + "\n", OpenJDKTestConfig.mavenProxyUrl())); + } catch (IOException e) { + //no op + } + } + } + + private void createMavenProxyConf() { + if (this.generateMirrorSettings) { + createMavenProxyConfXml(this.build.getPath()); + } + } + + + public void deploy() { + createMavenProxyConf(); + final String checkUrl = this.urlSuffix != null ? "http://" + this.hostname + "/" + this.urlSuffix : null; + checkUrlUnavailable(checkUrl); + + + this.appBuilder = ApplicationBuilder.fromManagedBuild(this.appName, BuildManagers.get().getBuildReference(build)); + + if (this.containerModification != null) { + this.containerModification.accept(this.appBuilder.deploymentConfig(this.appName) + .podTemplate() + .container()); + } + + log.info("Creating deployment config for {} with {} replicas.", this.appName, this.replicas); + this.appBuilder.deploymentConfig(this.appName) + .setReplicas(this.replicas) + .podTemplate() + .container() + .envVars(this.deploymentEnvironmentVariables); + this.appBuilder.service().port("http", 8080, 80); + this.appBuilder.route(); + + configureJolokia(this.appBuilder); + + if (this.persistentVolumeClaim != null) { + this.appBuilder.deploymentConfig().podTemplate() + .addPersistenVolumeClaim(this.persistentVolumeClaim.getName(), this.persistentVolumeClaim.getClaimName()); + this.appBuilder.deploymentConfig().podTemplate().container() + .addVolumeMount(this.persistentVolumeClaim.getName(), this.pvcMountPath, false); + } + + addComputingResources(this.appBuilder); + addProbes(); + configureSsl(this.appBuilder); + createDatabase(this.appBuilder, this.dbPostDeployment); + final String secureCheckUrl = this.secureUrlSuffix != null ? "https://" + this.secureHostName + "/" + this.secureUrlSuffix : null; + + // wait for build to finish + if (build != null) { + // fallback if build is not started via `@UsesBuild` annotation + if (!build.isPresent(OpenShifts.master(BuildManagerConfig.namespace()))) { + BuildManagers.get().deploy(build); + } + BuildManagers.get().hasBuildCompleted(build).waitFor(); + } + + this.appBuilder.buildApplication().deploy(); + OpenShifts.master().waiters().areExactlyNPodsReady(this.replicas, this.appName).waitFor(); + waitForCheckUrl(checkUrl); + waitForCheckUrl(secureCheckUrl); + + //final Map deploymentOutputMap = new HashMap<>(); + //insertDeployment(deploymentOutputMap); + deleteMavenProxyConf(); +// if (this.database != null) { +// return new Deployment(null, new HashMap(), deploymentOutputMap, "db"); +// } else { +// return new Deployment(null, new HashMap(), deploymentOutputMap, "no-db"); +// } + + } + + private void addProbes() { + if (this.readinessProbe != null) { + this.appBuilder.deploymentConfig() + .podTemplate() + .container() + .addReadinessProbe(this.readinessProbe); + } + } + + private void configureJolokia(final ApplicationBuilder appBuilder) { + if (isJolokiaEnabled()) { + appBuilder.deploymentConfig() + .podTemplate() + .container() + .envVar("AB_JOLOKIA_CONFIG", this.jolokiaConf.getConfigFile()) + .envVar("AB_JOLOKIA_AUTH_OPENSHIFT", String.valueOf(this.jolokiaConf.isAuthOpenShift())) + .envVar("AB_JOLOKIA_HOST", this.jolokiaConf.getHost()) + .envVar("AB_JOLOKIA_PORT", String.valueOf(this.jolokiaConf.getPort())) + .envVar("AB_JOLOKIA_DISCOVERY_ENABLED", String.valueOf(this.jolokiaConf.isDiscoveryEnabled())) + .envVar("AB_JOLOKIA_USER", this.jolokiaConf.getUser()) + .envVar("AB_JOLOKIA_HTTPS", String.valueOf(this.jolokiaConf.getHttps())) + .envVar("AB_JOLOKIA_PASSWORD", this.jolokiaConf.getPassword()) + .envVar("AB_JOLOKIA_PASSWORD_RANDOM", String.valueOf(this.jolokiaConf.isRandomPassword())) + .envVar("AB_JOLOKIA_OPTS", this.jolokiaConf.getAdditionalOpts()); + //default Jolokia access through OSE auth "Connect" + appBuilder.deploymentConfig() + .podTemplate() + .container() + .port(this.jolokiaConf.getPort(), this.jolokiaConf.getPortName()); + if (!this.jolokiaConf.isAuthOpenShift()) { + //expose Jolokia API if it's insecure + final String serviceRouteLabel = this.appName + "-jk"; + appBuilder.service(serviceRouteLabel) + .port(this.jolokiaConf.getPort()); + this.jolokiaHostname = OpenShifts.master().generateHostname(serviceRouteLabel); + appBuilder.route(serviceRouteLabel) + .forService(serviceRouteLabel) + .exposedAsHost(this.jolokiaHostname); + } + } else { + appBuilder.deploymentConfig(this.appName) + .podTemplate() + .container() + .envVar("AB_JOLOKIA_OFF", "true"); + } + } + + private void addComputingResources(final ApplicationBuilder appBuilder) { + if (this.cpuResource != null) { + final ComputingResource resource = appBuilder.deploymentConfig(this.appName) + .podTemplate() + .container() + .addCPUResource(); + resource.setRequests(this.cpuResource.getRequests()); + resource.setLimits(this.cpuResource.getLimits()); + } + + if (this.memoryResource != null) { + final ComputingResource resource = appBuilder.deploymentConfig(this.appName) + .podTemplate() + .container() + .addMemoryResource(); + resource.setRequests(this.memoryResource.getRequests()); + resource.setLimits(this.memoryResource.getLimits()); + } + } + + private void deleteMavenProxyConf() { + if (this.generateMirrorSettings) { + log.info("Deleting configuration dir with settings.xml"); + try { + Files.deleteIfExists(this.build.getPath().resolve("configuration/settings.xml")); + Files.deleteIfExists((this.build.getPath()).resolve("configuration")); + } catch (final IOException e) { + log.debug("Cannot delete configuration dir.", e); + } + } + } + + private void createDatabase(final ApplicationBuilder appBuilder, final boolean postDeployment) { + if (this.database != null) { + if (postDeployment) { + this.database.configureApplicationDeployment(appBuilder.deploymentConfig()); + this.dbPostDeploymentName = this.database.configureDeployment(appBuilder, false).setReplicas(0).getName(); + } else { + appBuilder.addDatabase(this.database); + } + } + } + + public void postDbDeployment() { + if (this.database != null && this.appBuilder != null && this.dbPostDeploymentName != null) { + log.info("Database post deployment"); + OpenShifts.master().scale(this.dbPostDeploymentName, 1); + OpenShifts.master().deployLatest(this.dbPostDeploymentName); + } + } + + private void configureSsl(final ApplicationBuilder appBuilder) { + if (this.ssl) { + OpenShift openShift = OpenShifts.master(); + this.secureHostName = openShift.generateHostname(this.appName + "-secure"); + final Path keystorePath = ProcessKeystoreGenerator.generateKeystore(this.secureHostName, this.appName, this.deleteCaFromKeyStore); + + final SecretBuilder sb = new SecretBuilder(); + final String secretName = this.appName + "-ssl"; + sb.withNewMetadata() + .withName(secretName) + .endMetadata(); + try { + sb.addToData("keystore", + Base64.encodeBase64String(FileUtils.readFileToByteArray(keystorePath.toFile()))); + } catch (final IOException e) { + throw new RuntimeException(e); + } + + openShift.createSecret(sb.build()); + + appBuilder.deploymentConfig(this.appName) + .podTemplate() + .container() + .addVolumeMount("ssl", "/ssl", true); + appBuilder.deploymentConfig(this.appName) + .podTemplate() + .container() + .port(8443); + appBuilder.deploymentConfig(this.appName) + .podTemplate() + .addSecretVolume("ssl", secretName); + appBuilder.service(this.appName + "-https") + .port("https" ,8443, 443); + appBuilder.route(this.appName + "-secure") + .exposedAsHost(this.secureHostName) + .passthrough() + .forService( + this.appName + "-https"); + } + } + + private void waitForCheckUrl(final String checkUrl) { + if (checkUrl != null) { + try { + Http.get(checkUrl).trustAll().waiters().ok().waitFor(); + } catch (MalformedURLException e) { + log.error(e.getMessage()); + } + } + } + +// private void insertDeployment(final Map deploymentOutputMap) { +// switch (this.deyplotmentType) { +// case SPRING_BOOT: +// deploymentOutputMap.put(this.appName, new SpringBootDeployment(this.appName, this.hostname, null, +// this.secureHostName)); +// break; +// case JAVA_S2I: +// deploymentOutputMap.put(this.appName, +// new JavaS2IDeployment(this.appName, this.hostname, null, this.jolokiaHostname)); +// break; +// case WILDFLY_SWARM: +// deploymentOutputMap.put(this.appName, +// new WildFlySwarmDeployment(this.appName, this.hostname, null, this.secureHostName)); +// } +// } + + private void checkUrlUnavailable(final String checkUrl) { + if (checkUrl != null) { + try { + Assertions.assertEquals(503, Http.get(checkUrl).execute().code()); + } catch (final Exception x) { + // ignore + } + } + } + +// private void reportRestartFailure(final String appName) { +// OpenShiftBinaryClient.getInstance() +// .project(OpenshiftUtil.getInstance() +// .getContext() +// .getNamespace()); +// final String previousLogs = OpenShiftBinaryClient.getInstance() +// .executeCommandWithReturn( +// "Pod " + appName + " has restarted, presumably failing. Cannot retreive previous pod logs, sorry.", +// "logs", OpenshiftUtil.getInstance() +// .findNamedPod(appName) +// .getMetadata() +// .getName(), "-p"); +// +// Assertions.fail("Pod " + appName + " has restarted, presumably failing. Previous pod logs:\n" + previousLogs); +// } + + public boolean isJolokiaEnabled() { + return this.jolokiaConf != null && this.jolokiaConf.isEnabled(); + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/MsaDeploymentType.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/MsaDeploymentType.java new file mode 100644 index 0000000..09ac34c --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/MsaDeploymentType.java @@ -0,0 +1,8 @@ +package com.redhat.qe.openjdk.util.deployment; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +public enum MsaDeploymentType { + SPRING_BOOT, WILDFLY_SWARM, JAVA_S2I; +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/SpringBootDeployment.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/SpringBootDeployment.java new file mode 100644 index 0000000..1d0667b --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/SpringBootDeployment.java @@ -0,0 +1,19 @@ +package com.redhat.qe.openjdk.util.deployment; + +import com.redhat.qe.openjdk.util.AbstractServerDeployment; + +/** + * @author Radek Koubsky (rkoubsky@redhat.com) + */ +public class SpringBootDeployment extends AbstractServerDeployment { + + public SpringBootDeployment(final String name, final String hostName, final String cluster) { + this(name, hostName, cluster, null); + } + + public SpringBootDeployment(final String name, final String hostName, final String cluster, + final String secureHostname) { + super(name, hostName, cluster, secureHostname); + + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/WildFlySwarmDeployment.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/WildFlySwarmDeployment.java new file mode 100644 index 0000000..51b9074 --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/deployment/WildFlySwarmDeployment.java @@ -0,0 +1,14 @@ +package com.redhat.qe.openjdk.util.deployment; + +import com.redhat.qe.openjdk.util.AbstractServerDeployment; + +public class WildFlySwarmDeployment extends AbstractServerDeployment { + public WildFlySwarmDeployment(final String name, final String hostName, final String cluster) { + this(name, hostName, cluster, null); + } + + public WildFlySwarmDeployment(final String name, final String hostName, final String cluster, + final String secureHostname) { + super(name, hostName, cluster, secureHostname); + } +} diff --git a/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/maven/PomModifier.java b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/maven/PomModifier.java new file mode 100644 index 0000000..a7ae80c --- /dev/null +++ b/test-openjdk/src/test/java/com/redhat/qe/openjdk/util/maven/PomModifier.java @@ -0,0 +1,215 @@ +package com.redhat.qe.openjdk.util.maven; + +import org.apache.commons.io.FileUtils; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PomModifier { + + private static DocumentBuilderFactory builderFactory; + private static DocumentBuilder builder; + private static TransformerFactory transformerFactory; + private static Transformer transformer; + + private Document parsedDocument; + private Path projectPomFile; + private Path projectDirectory; + private Path gitDirectory; + private Path parentPomFile; + private Path parentDirectory; + + public void modify(Path projectDirectory, Path gitDirectory) { + if (builderFactory == null) { + builderFactory = DocumentBuilderFactory.newInstance(); + transformerFactory = TransformerFactory.newInstance(); + try { + builder = builderFactory.newDocumentBuilder(); + transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + } catch (ParserConfigurationException | TransformerConfigurationException e) { + throw new IllegalStateException(e); + } + } + + projectPomFile = gitDirectory.resolve("pom.xml"); + this.projectDirectory = projectDirectory; + this.gitDirectory = gitDirectory; + + if (!modifyProjectPOM()) { + return; + } + + copyParentDirectory(); + //modifyParentPOM("eap-" + EapTestConfig.eapMajorVersion()); + } + + private Element childElement(final Element parentNode, final String elementName) { + List children = childElements(parentNode, elementName); + return children.size() > 0 ? children.get(0) : null; + } + + private Element createChildElement(final Element parentNode, final String elementName) { + final List children = childElements(parentNode, elementName); + if (children.size() > 0) { + return children.get(0); + } + final Element element = parsedDocument.createElement(elementName); + parentNode.appendChild(element); + return element; + } + + private List childElements(final Element parentNode, final String elementName) { + final List ret = new ArrayList<>(); + final NodeList nodes = parentNode.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element element = (Element)nodes.item(i); + if (elementName.equals(element.getTagName())) { + ret.add(element); + } + } + return ret; + } + + private String getElementText(final Node element) { + final NodeList nodes = element.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + if (nodes.item(i).getNodeType() == Node.TEXT_NODE) { + return nodes.item(i).getTextContent(); + } + } + return null; + } + + private void setElementText(final Node element, final String text) { + final NodeList nodes = element.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + if (nodes.item(i).getNodeType() == Node.TEXT_NODE) { + nodes.item(i).setTextContent(text); + return; + } + } + element.appendChild(parsedDocument.createTextNode(text)); + } + + private boolean modifyProjectPOM() { + log.info("Parsing POM {}", projectPomFile); + if (!projectPomFile.toFile().exists()) { + log.debug("Non-Maven project, skipping manipulation"); + return false; + } + try { + parseDocument(projectPomFile); + final Element root = parsedDocument.getDocumentElement(); + final Element parent = childElement(root, "parent"); + if (parent == null) { + log.debug("No parent found, skipping manipulation"); + return false; + } + final Element relativePath = childElement(parent, "relativePath"); + if (relativePath == null) { + log.error("Relative path required"); + throw new IllegalStateException("Relative path required in parent"); + } + final String parentLocation = getElementText(relativePath); + parentDirectory = projectDirectory.resolve(parentLocation).normalize().toAbsolutePath(); + if (!parentDirectory.toFile().exists()) { + throw new IllegalArgumentException("Parent directory does not exist " + parentDirectory); + } + relativePath.setTextContent(parentDirectory.toFile().getName()); + writePOMFile(projectPomFile, root); + } catch (SAXException | IOException | TransformerException e) { + throw new IllegalStateException(e); + + } + return true; + } + + private void modifyParentPOM(final String activatedProfile) { + log.info("Parsing POM {}", parentPomFile); + try { + parseDocument(parentPomFile); + final Element root = parsedDocument.getDocumentElement(); + final Element profiles = childElement(root, "profiles"); + if (profiles == null) { + log.debug("No profiles found, skipping manipulation"); + return; + } + childElements(profiles, "profile").forEach(profile -> { + final String id = getElementText(childElement(profile, "id")); + if (activatedProfile.equals(id)) { + activateProfile(profile); + } + else { + deactivateProfile(profile); + } + }); + writePOMFile(parentPomFile, root); + } catch (SAXException | IOException | TransformerException e) { + throw new IllegalStateException(e); + + } + } + + private Document parseDocument(final Path pomFile) throws SAXException, + IOException { + parsedDocument = builder.parse(pomFile.toFile()); + return parsedDocument; + } + + private void writePOMFile(final Path pomFile, final Element root) + throws FileNotFoundException, TransformerException, IOException { + FileOutputStream fos = new FileOutputStream(pomFile.toFile()); + transformer.transform(new DOMSource(root), new StreamResult(fos)); + fos.close(); + } + + private void activateProfile(final Element profile) { + setElementText(createChildElement(createChildElement(profile, "activation"), "activeByDefault"), "true"); + } + + private void deactivateProfile(final Element profile) { + setElementText(createChildElement(createChildElement(profile, "activation"), "activeByDefault"), "false"); + } + + private void copyParentDirectory() { + final Path parentDestDir = gitDirectory.resolve(parentDirectory.getFileName()); + parentDestDir.toFile().mkdir(); + try { + FileUtils.copyDirectory(parentDirectory.toFile(), parentDestDir.toFile()); + } catch (Exception e) { + throw new IllegalStateException(e); + } + parentPomFile = parentDestDir.resolve("pom.xml"); + } +} diff --git a/test-openjdk/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/test-openjdk/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension new file mode 100644 index 0000000..2e64b07 --- /dev/null +++ b/test-openjdk/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension @@ -0,0 +1 @@ +cz.xtf.junit5.extensions.JenkinsRerunCondition \ No newline at end of file diff --git a/test-openjdk/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/test-openjdk/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener new file mode 100644 index 0000000..80a5da1 --- /dev/null +++ b/test-openjdk/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener @@ -0,0 +1,5 @@ +cz.xtf.junit5.listeners.ConfigRecorder +cz.xtf.junit5.listeners.ProjectCreator +cz.xtf.junit5.listeners.PodLogRecorder +cz.xtf.junit5.listeners.TestExecutionLogger +cz.xtf.junit5.listeners.ManagedBuildPrebuilder diff --git a/test-openjdk/src/test/resources/apps/build-limits/pom.xml b/test-openjdk/src/test/resources/apps/build-limits/pom.xml new file mode 100644 index 0000000..70a3464 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/build-limits/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + com.redhat.qe.openjdk.common.deployments + build-limits + 1.0.0-SNAPSHOT + Build memory limits verifier + + + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20 + + 0 + + + + + + diff --git a/test-openjdk/src/test/resources/apps/build-limits/src/main/java/org/jboss/qe/openjdk/buildlimits/Main.java b/test-openjdk/src/test/resources/apps/build-limits/src/main/java/org/jboss/qe/openjdk/buildlimits/Main.java new file mode 100644 index 0000000..1cb267e --- /dev/null +++ b/test-openjdk/src/test/resources/apps/build-limits/src/main/java/org/jboss/qe/openjdk/buildlimits/Main.java @@ -0,0 +1,7 @@ +package org.jboss.qe.openjdk.buildlimits; + +public class Main { + + public static void main(final String[] arg) { + } +} diff --git a/test-openjdk/src/test/resources/apps/build-limits/src/test/java/org/jboss/qe/openjdk/buildlimits/MemorySettingsTest.java b/test-openjdk/src/test/resources/apps/build-limits/src/test/java/org/jboss/qe/openjdk/buildlimits/MemorySettingsTest.java new file mode 100644 index 0000000..00e5c23 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/build-limits/src/test/java/org/jboss/qe/openjdk/buildlimits/MemorySettingsTest.java @@ -0,0 +1,54 @@ +package org.jboss.qe.openjdk.buildlimits; + +import org.junit.Test; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; + +public class MemorySettingsTest { + + @Test + public void printMemoryUsage() { + System.out.printf("HeapMemoryUsage: %s\n", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()); + System.out.printf("NonHeapMemoryUsage: %s\n", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()); + + for (MemoryPoolMXBean mpBean: ManagementFactory.getMemoryPoolMXBeans()) { + System.out.printf("%s %s: %s\n", mpBean.getType(), mpBean.getName(), mpBean.getUsage()); + } + } + + @Test + public void test() { + String op = System.getenv("COMPARE"); + final String arg = System.getenv("ARG"); + final String arg1 = System.getenv("ARG1"); + final String arg2 = System.getenv("ARG2"); + final long totalMemory = Runtime.getRuntime().totalMemory(); + final long initialHeapMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getInit(); + final long maxHeapMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax(); + + System.out.println(String.format("Operation %s, value %s, totalMemory %s initialHeapMemory %s maxHeapMemory %s", op, arg, totalMemory, initialHeapMemory, maxHeapMemory)); + System.out.println(String.format("MAVEN_OPTS=%s", System.getenv("MAVEN_OPTS"))); + + if (op != null) { + switch (op) { + case "eq": + assert totalMemory == Long.parseLong(arg); + break; + case "gt": + assert totalMemory >= Long.parseLong(arg); + break; + case "lt": + assert totalMemory <= Long.parseLong(arg); + break; + case "rng": + assert totalMemory >= Long.parseLong(arg1) && totalMemory <= Long.parseLong(arg2); + break; + case "heaprng": + assert initialHeapMemory >= Long.parseLong(arg1) && maxHeapMemory <= Long.parseLong(arg2); + break; + } + } + } + +} diff --git a/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/pom.xml b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/pom.xml new file mode 100644 index 0000000..a90719e --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + + com.redhat.qe.openjdk + parent-msa-sb + 2.0.0-SNAPSHOT + ../parent-msa-sb + + + com.redhat.qe.openjdk + docker-image-test-app + jar + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.yaml + snakeyaml + test + + + + + + fat-jar + + true + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + + + regular-jar + + ${project.artifactId} + + + maven-dependency-plugin + + + generate-sources + + copy-dependencies + + + ${project.build.directory}/lib + true + + + + build-classpath + generate-resources + + build-classpath + + + ${project.build.directory}/lib/classpath + lib + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repackage + none + + + + + + + + diff --git a/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/prometheus/jmx-exporter-config-custom.yaml b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/prometheus/jmx-exporter-config-custom.yaml new file mode 100644 index 0000000..bb04866 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/prometheus/jmx-exporter-config-custom.yaml @@ -0,0 +1,22 @@ +# +# Copyright 2018 Red Hat, Inc. and/or its affiliates +# and other contributors as indicated by the @author tags. +# +# Licensed 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. +# +--- +lowercaseOutputName: true +lowercaseOutputLabelNames: true +#blacklistObjectNames: +# handled by agent's default exporter +#- "java.lang:*" diff --git a/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/SampleTomcatApplication.java b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/SampleTomcatApplication.java new file mode 100644 index 0000000..f3e170e --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/SampleTomcatApplication.java @@ -0,0 +1,11 @@ +package com.redhat.qe.openjdk.springboot.tomcat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleTomcatApplication { + public static void main(final String[] args) throws Exception { + SpringApplication.run(SampleTomcatApplication.class, args); + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/web/HelloRs.java b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/web/HelloRs.java new file mode 100644 index 0000000..3c36b67 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/web/HelloRs.java @@ -0,0 +1,14 @@ +package com.redhat.qe.openjdk.springboot.tomcat.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class HelloRs { + @GetMapping("/") + @ResponseBody + public String helloWorld() { + return "Hello world!"; + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/web/RuntimeRs.java b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/web/RuntimeRs.java new file mode 100644 index 0000000..0dd3e48 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/docker-image-test-app/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/web/RuntimeRs.java @@ -0,0 +1,20 @@ +package com.redhat.qe.openjdk.springboot.tomcat.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class RuntimeRs { + @GetMapping("/availableProcessors") + @ResponseBody + public int availableProcessors() { + return Runtime.getRuntime().availableProcessors(); + } + + @GetMapping("/maxMemory") + @ResponseBody + public long maxMemory() { + return Runtime.getRuntime().maxMemory(); + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/pom.xml b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/pom.xml new file mode 100644 index 0000000..5195c35 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + com.redhat.qe.openjdk + parent-msa-sb + 2.0.0-SNAPSHOT + ../parent-msa-sb + + + noha-servlet-counter-sb + Spring Boot Servlet Counter + Spring Boot Servlet Counter + jar + + + + org.springframework.boot + spring-boot-starter-web + + + + + + ${project.artifactId} + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${qe.openjdk.test.fail} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + diff --git a/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/NohaTomcatApplication.java b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/NohaTomcatApplication.java new file mode 100644 index 0000000..cdb1141 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/NohaTomcatApplication.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed 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 com.redhat.qe.openjdk.tomcat.noha; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import java.util.UUID; + +@SpringBootApplication +public class NohaTomcatApplication { + + private static Log logger = LogFactory.getLog(NohaTomcatApplication.class); + + @Bean + protected ServletContextListener listener() { + return new ServletContextListener() { + + @Override + public void contextInitialized(ServletContextEvent sce) { + sce.getServletContext().setAttribute("servletId", UUID.randomUUID().toString()); + logger.info("ServletContext initialized, servletId: " + sce.getServletContext().getAttribute("servletId")); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + logger.info("ServletContext destroyed"); + } + + }; + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(NohaTomcatApplication.class, args); + } + +} diff --git a/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/DisableServlet.java b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/DisableServlet.java new file mode 100644 index 0000000..df8279c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/DisableServlet.java @@ -0,0 +1,23 @@ +package com.redhat.qe.openjdk.tomcat.noha.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; + +/** + * Simple Servlet-based session-scoped counter + * + * @author lfuka + */ +@Controller +public class DisableServlet { + + @GetMapping(path="/Disable", produces="text/plain") + @ResponseBody + public String disableCounter(HttpServletRequest req) { + req.getServletContext().setAttribute("counterDisabled", new Boolean(true)); + return "counter disabled"; + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/EnableServlet.java b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/EnableServlet.java new file mode 100644 index 0000000..721c7aa --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/EnableServlet.java @@ -0,0 +1,23 @@ +package com.redhat.qe.openjdk.tomcat.noha.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; + +/** + * Simple Servlet-based session-scoped counter + * + * @author lfuka + */ +@Controller +public class EnableServlet { + + @GetMapping(path="/Enable", produces="text/plain") + @ResponseBody + public String enableCounter(HttpServletRequest req) { + req.getServletContext().setAttribute("counterDisabled", new Boolean(false)); + return "counter enabled"; + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/ServletCounter.java b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/ServletCounter.java new file mode 100644 index 0000000..24e9696 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/tomcat/noha/web/ServletCounter.java @@ -0,0 +1,48 @@ +package com.redhat.qe.openjdk.tomcat.noha.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import java.io.IOException; + +/** + * Simple Servlet-based session-scoped counter + * + * @author lfuka + */ +@Controller +public class ServletCounter { + + @GetMapping(path="/Counter", produces="text/plain") + @ResponseBody + public String counter(HttpServletRequest req) { + String servletId = (String) req.getServletContext().getAttribute("servletId"); + Boolean disabled = (Boolean) req.getServletContext().getAttribute("counterDisabled"); + + if (disabled != null && disabled.booleanValue()) { + throw new IllegalArgumentException("Counter servlet temporarily disabled, sorry!"); + } + + HttpSession session = req.getSession(); + Long counter = (Long) session.getAttribute("counter"); + if (counter == null) { + counter = 0L; + } + counter++; + session.setAttribute("counter", counter); + + return servletId + " " + counter; + } + + @ExceptionHandler + private void handleIllegalArgumentException(IllegalArgumentException e, HttpServletResponse response) throws IOException { + response.sendError(503, "Counter servlet temporarily disabled, sorry!"); + } + +} diff --git a/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/webapp/index.html b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/webapp/index.html new file mode 100644 index 0000000..cfd615f --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/noha-servlet-counter/src/main/webapp/index.html @@ -0,0 +1,5 @@ + + + + + diff --git a/test-openjdk/src/test/resources/apps/springboot/parent-msa-sb/pom.xml b/test-openjdk/src/test/resources/apps/springboot/parent-msa-sb/pom.xml new file mode 100644 index 0000000..9baeb9d --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/parent-msa-sb/pom.xml @@ -0,0 +1,144 @@ + + + + 4.0.0 + + com.redhat.qe.openjdk + parent-msa-sb + pom + 2.0.0-SNAPSHOT + + OpenJDKQe :: Msa :: Productized SpringBoot Parent + Productized SpringBoot Parent for QE Msa test deployments + + + UTF-8 + 3.1 + 1.8 + 1.8 + 3.1.0 + + 3.1.80.redhat-000010 + 2.3.7 + 2.18.1 + 2.18.1 + + 2.1.3.RELEASE + 2.1.3.Final-redhat-00001 + + 12.2.0.1 + 42.1.4 + 5.1.44 + 3.3.0 + + 20180813 + 1.4.197 + + + + + + me.snowdrop + spring-boot-bom + ${spring-boot.bom.version} + pom + import + + + + + org.postgresql + postgresql + ${postgresql.version} + + + + mysql + mysql-connector-java + ${version.mysql.mysql-connector-java} + + + + org.mongodb + mongo-java-driver + ${mongodb.version} + + + + com.oracle.jdbc + ojdbc8 + ${oracle.jdbc.version} + + + + org.json + json + ${org.json.version} + + + + com.h2database + h2 + ${com.h2database.version} + + + + + + + + + + org.apache.felix + maven-bundle-plugin + ${version.maven-bundle-plugin} + + + org.springframework.boot + spring-boot-maven-plugin + ${version.org.springframework.boot} + + + io.fabric8 + fabric8-maven-plugin + ${fabric8.maven.plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.plugin.version} + + + org.apache.maven.plugins + maven-war-plugin + ${maven.war.plugin.version} + + + + maven-compiler-plugin + ${maven.compiler.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repackage + + repackage + + + + + + + diff --git a/test-openjdk/src/test/resources/apps/springboot/parent-msa-sb/pom.xml.upstream b/test-openjdk/src/test/resources/apps/springboot/parent-msa-sb/pom.xml.upstream new file mode 100644 index 0000000..25bbb20 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/parent-msa-sb/pom.xml.upstream @@ -0,0 +1,121 @@ + + + + 4.0.0 + + com.redhat.qe.openjdk + parent-msa-sb + pom + 2.0.0-SNAPSHOT + + OpenJDKQe :: Msa :: Upstream SpringBoot Parent + Upstream SpringBoot Parent for QE Msa test deployments + + + UTF-8 + 3.1 + 1.8 + 1.8 + + 3.1.80.redhat-000010 + 2.3.7 + 2.18.1 + 2.18.1 + + 1.5.17.RELEASE + 1.5.17.Final + + 12.2.0.1 + 42.1.4 + 5.1.44 + 3.3.0 + + + + + + me.snowdrop + spring-boot-bom + ${spring-boot.bom.version} + pom + import + + + + + org.postgresql + postgresql + ${postgresql.version} + + + + mysql + mysql-connector-java + ${version.mysql.mysql-connector-java} + + + + org.mongodb + mongo-java-driver + ${mongodb.version} + + + + com.oracle.jdbc + ojdbc8 + ${oracle.jdbc.version} + + + + + + + + org.apache.felix + maven-bundle-plugin + ${version.maven-bundle-plugin} + + + org.springframework.boot + spring-boot-maven-plugin + ${version.org.springframework.boot} + + + io.fabric8 + fabric8-maven-plugin + ${fabric8.maven.plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.plugin.version} + + + + maven-compiler-plugin + ${maven.compiler.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repackage + + repackage + + + + + + + diff --git a/test-openjdk/src/test/resources/apps/springboot/ssl/pom.xml b/test-openjdk/src/test/resources/apps/springboot/ssl/pom.xml new file mode 100644 index 0000000..25b9392 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/ssl/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + com.redhat.qe.openjdk + parent-msa-sb + 2.0.0-SNAPSHOT + ../parent-msa-sb + + + ssl + jar + + + + org.springframework.boot + spring-boot-starter-web + + + \ No newline at end of file diff --git a/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/SampleTomcatApplication.java b/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/SampleTomcatApplication.java new file mode 100644 index 0000000..59c1d6c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/SampleTomcatApplication.java @@ -0,0 +1,46 @@ +package com.redhat.qe.openjdk.springboot.tomcat; + +import org.apache.catalina.connector.Connector; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +import com.redhat.qe.openjdk.springboot.tomcat.ssl.ConnectionParameterServlet; + +/** + * @author Radek Koubsky (radekkoubsky@gmail.com) + */ +@SpringBootApplication +public class SampleTomcatApplication { + public static void main(final String[] args) throws Exception { + SpringApplication.run(SampleTomcatApplication.class, args); + } + + @Bean + public Integer port() { + return 8080; + } + + @Bean + public ServletWebServerFactory servletContainer() { + final TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + tomcat.addAdditionalTomcatConnectors(createStandardConnector()); + return tomcat; + } + + + private Connector createStandardConnector() { + final Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); + connector.setPort(port()); + return connector; + } + + @Bean + public ServletRegistrationBean delegateServiceExporterServlet() { + return new ServletRegistrationBean(new ConnectionParameterServlet(), "/connectionInfo"); + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/ssl/ConnectionParameterServlet.java b/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/ssl/ConnectionParameterServlet.java new file mode 100644 index 0000000..c2a3c3e --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/java/com/redhat/qe/openjdk/springboot/tomcat/ssl/ConnectionParameterServlet.java @@ -0,0 +1,29 @@ +package com.redhat.qe.openjdk.springboot.tomcat.ssl; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + +/** + * @author Radek Koubsky (radekkoubsky@gmail.com) + */ +public class ConnectionParameterServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + public ConnectionParameterServlet() { + super(); + } + + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) + throws ServletException, IOException { + final String paramName = request.getParameter("param"); + String returnValue = ""; + if ("secure".equals(paramName)) { + returnValue = Boolean.toString(request.isSecure()); + } + response.getOutputStream().println(returnValue); + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/resources/application.properties b/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/resources/application.properties new file mode 100644 index 0000000..0aa0a1c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/ssl/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.port=8443 +server.ssl.key-store=/ssl/keystore +server.ssl.key-store-password=password +server.ssl.key-password=password \ No newline at end of file diff --git a/test-openjdk/src/test/resources/apps/springboot/sti/pom.xml b/test-openjdk/src/test/resources/apps/springboot/sti/pom.xml new file mode 100644 index 0000000..36d5435 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/sti/pom.xml @@ -0,0 +1,104 @@ + + + 4.0.0 + + com.redhat.qe.openjdk + parent-msa-sb + 2.0.0-SNAPSHOT + ../parent-msa-sb + + + sti + Spring Boot Tomcat Sample + Spring Boot Tomcat Sample + http://projects.spring.io/spring-boot/ + jar + + + **/Broken*.java + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-actuator + + + junit + junit + 4.12 + test + + + + + + ${project.artifactId} + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${qe.openjdk.test.fail} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + ${qe.openjdk.broken.file} + + + + + + + + + openshift + + + broken-deps + + + broken-repository + http://broken.repo + + true + + + false + + + + + + broken-group + broken-artifact + 1.0.0.Final + + + + + fail-test + + true + + + + compile-error + + Ignore + + + + diff --git a/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/SampleTomcatApplication.java b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/SampleTomcatApplication.java new file mode 100644 index 0000000..b9b07c3 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/SampleTomcatApplication.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed 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 sample.tomcat; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +@SpringBootApplication +public class SampleTomcatApplication { + + private static Log logger = LogFactory.getLog(SampleTomcatApplication.class); + + @Bean + protected ServletContextListener listener() { + return new ServletContextListener() { + + @Override + public void contextInitialized(ServletContextEvent sce) { + logger.info("ServletContext initialized"); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + logger.info("ServletContext destroyed"); + } + + }; + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(SampleTomcatApplication.class, args); + } + +} diff --git a/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/service/BrokenService.java b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/service/BrokenService.java new file mode 100644 index 0000000..1e918b4 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/service/BrokenService.java @@ -0,0 +1,10 @@ +package sample.tomcat.service; + +/** + * Its needed for STI tests + */ +public class BrokenService { + + public String sayHello(String name) { + } +} diff --git a/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/service/HelloWorldService.java b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/service/HelloWorldService.java new file mode 100644 index 0000000..f05d6e1 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/service/HelloWorldService.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed 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 sample.tomcat.service; + +import org.springframework.stereotype.Component; + +@Component +public class HelloWorldService { + + public String getHelloMessage(String name) { + return "Initial " + name; + } + +} diff --git a/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/web/SampleController.java b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/web/SampleController.java new file mode 100644 index 0000000..4a080cc --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/sti/src/main/java/sample/tomcat/web/SampleController.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed 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 sample.tomcat.web; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import sample.tomcat.service.HelloWorldService; + +@Controller +public class SampleController { + + @Autowired + private HelloWorldService helloWorldService; + + @GetMapping("/HelloWorld") + @ResponseBody + public String helloWorld(@RequestParam(value="name") String name) { + return this.helloWorldService.getHelloMessage(name); + } + + @GetMapping("/ping") + @ResponseBody + public String ping() { + return "pong"; + } + +} diff --git a/test-openjdk/src/test/resources/apps/springboot/sti/src/test/java/com/redhat/qe/openjdk/sti/ShouldFailTest.java b/test-openjdk/src/test/resources/apps/springboot/sti/src/test/java/com/redhat/qe/openjdk/sti/ShouldFailTest.java new file mode 100644 index 0000000..ae267fc --- /dev/null +++ b/test-openjdk/src/test/resources/apps/springboot/sti/src/test/java/com/redhat/qe/openjdk/sti/ShouldFailTest.java @@ -0,0 +1,14 @@ +package com.redhat.qe.openjdk.sti; + +import org.junit.Assert; +import org.junit.Test; + +public class ShouldFailTest { + + @Test + public void shouldFailTest() { + if ("true".equals(System.getProperty("qe.openjdk.test.fail", "false"))) { + Assert.fail("Failed upon request"); + } + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/pom.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/pom.xml new file mode 100644 index 0000000..05eefc5 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.redhat.qe.openjdk + parent-msa-wildfly-swarm + 2.0.0-SNAPSHOT + ../parent-msa-wildfly-swarm + + + hello-world-wildfly-swarm + WildFly Swarm Hello World + WildFly Swarm Hello World + war + + + + io.thorntail + undertow + + + + + ${project.artifactId} + + + + io.thorntail + thorntail-maven-plugin + ${thorntail.version} + + + + package + + + + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/src/main/java/com/redhat/qe/openjdk/swarm/helloworld/HelloWorldServlet.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/src/main/java/com/redhat/qe/openjdk/swarm/helloworld/HelloWorldServlet.java new file mode 100644 index 0000000..6e36670 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/src/main/java/com/redhat/qe/openjdk/swarm/helloworld/HelloWorldServlet.java @@ -0,0 +1,15 @@ +package com.redhat.qe.openjdk.swarm.helloworld; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet("/") +public class HelloWorldServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.getWriter().print("Hello, World!"); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/src/main/webapp/WEB-INF/web.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..7fd775c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/hello-world/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/pom.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/pom.xml new file mode 100644 index 0000000..5e2f2fd --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + com.redhat.qe.openjdk + parent-msa-wildfly-swarm + 2.0.0-SNAPSHOT + ../parent-msa-wildfly-swarm + + + noha-servlet-counter-wildfly-swarm + WildFly Swarm Servlet Counter + WildFly Swarm Servlet Counter + war + + + + io.thorntail + undertow + + + + + + ${project.artifactId} + + + + io.thorntail + thorntail-maven-plugin + ${thorntail.version} + + + + package + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + ${qe.openjdk.test.fail} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/NohaServletContextListener.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/NohaServletContextListener.java new file mode 100644 index 0000000..89c380b --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/NohaServletContextListener.java @@ -0,0 +1,24 @@ +package com.redhat.qe.openjdk.swarm.noha; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +import java.util.UUID; +import java.util.logging.Logger; + +@WebListener +public class NohaServletContextListener implements ServletContextListener { + private static Logger logger = Logger.getLogger(NohaServletContextListener.class.getName()); + + @Override + public void contextInitialized(ServletContextEvent sce) { + sce.getServletContext().setAttribute("servletId", UUID.randomUUID().toString()); + logger.info("ServletContext initialized, servletId: " + sce.getServletContext().getAttribute("servletId")); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + logger.info("ServletContext destroyed"); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/CounterServlet.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/CounterServlet.java new file mode 100644 index 0000000..99fbaef --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/CounterServlet.java @@ -0,0 +1,33 @@ +package com.redhat.qe.openjdk.swarm.noha.web; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import java.io.IOException; + +@WebServlet("/Counter") +public class CounterServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String servletId = (String) req.getServletContext().getAttribute("servletId"); + Boolean disabled = (Boolean) req.getServletContext().getAttribute("counterDisabled"); + + if (disabled != null && disabled.booleanValue()) { + resp.sendError(503, "Counter servlet temporarily disabled, sorry!"); + return; + } + + HttpSession session = req.getSession(); + Long counter = (Long) session.getAttribute("counter"); + if (counter == null) { + counter = 0L; + } + counter++; + session.setAttribute("counter", counter); + + resp.getWriter().println(servletId + " " + counter); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/DisableServlet.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/DisableServlet.java new file mode 100644 index 0000000..f398ee0 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/DisableServlet.java @@ -0,0 +1,17 @@ +package com.redhat.qe.openjdk.swarm.noha.web; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/Disable") +public class DisableServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + req.getServletContext().setAttribute("counterDisabled", new Boolean(true)); + resp.getWriter().println("counter disabled"); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/EnableServlet.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/EnableServlet.java new file mode 100644 index 0000000..8ff6ae1 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/java/com/redhat/qe/openjdk/swarm/noha/web/EnableServlet.java @@ -0,0 +1,17 @@ +package com.redhat.qe.openjdk.swarm.noha.web; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/Enable") +public class EnableServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + req.getServletContext().setAttribute("counterDisabled", new Boolean(false)); + resp.getWriter().println("counter enabled"); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/webapp/WEB-INF/web.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..7fd775c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/webapp/index.html b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/webapp/index.html new file mode 100644 index 0000000..cfd615f --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/noha-servlet-counter/src/main/webapp/index.html @@ -0,0 +1,5 @@ + + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/parent-msa-wildfly-swarm/pom.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/parent-msa-wildfly-swarm/pom.xml new file mode 100644 index 0000000..89d7899 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/parent-msa-wildfly-swarm/pom.xml @@ -0,0 +1,131 @@ + + + + 4.0.0 + + com.redhat.qe.openjdk + parent-msa-wildfly-swarm + pom + 2.0.0-SNAPSHOT + + qe :: Msa :: WildFly Swarm Parent + WildFly Swarm Parent for QE Msa test deployments + + + UTF-8 + 3.1 + 1.8 + 1.8 + + + 2.5.0.Final-redhat-00016 + + 2.1.5.Final + 1.4.0.Final + + 12.2.0.1 + 42.1.4 + 5.1.44 + + + + + + io.thorntail + bom + ${thorntail.version} + import + pom + + + + + org.postgresql + postgresql + ${postgresql.version} + + + + + mysql + mysql-connector-java + ${version.mysql.mysql-connector-java} + + + + + com.oracle.jdbc + ojdbc8 + ${oracle.jdbc.version} + + + + + + + ibm-jdk + + + + org.apache.maven.plugins + maven-dependency-plugin + + + download-jboss-logmanager + generate-resources + + copy + + + true + + + org.jboss.logmanager + jboss-logmanager + ${version.org.jboss.logmanager} + + + org.wildfly.common + wildfly-common + ${version.org.wildfly.common} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/pom.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/pom.xml new file mode 100644 index 0000000..082d04c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + + com.redhat.qe.openjdk + parent-msa-wildfly-swarm + 2.0.0-SNAPSHOT + ../parent-msa-wildfly-swarm + + + com.redhat.qe.openjdk + ssl-wildfly-swarm + war + + + + + io.thorntail + management + + + io.thorntail + undertow + + + + + ${project.artifactId} + + + + io.thorntail + thorntail-maven-plugin + ${thorntail.version} + + + + package + + + + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/java/com/redhat/qe/openjdk/swarm/ssl/ConnectionParameterServlet.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/java/com/redhat/qe/openjdk/swarm/ssl/ConnectionParameterServlet.java new file mode 100644 index 0000000..cac0384 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/java/com/redhat/qe/openjdk/swarm/ssl/ConnectionParameterServlet.java @@ -0,0 +1,22 @@ +package com.redhat.qe.openjdk.swarm.ssl; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/connectionInfo") +public class ConnectionParameterServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + final String paramName = req.getParameter("param"); + String returnValue = ""; + if ("secure".equals(paramName)) { + returnValue = Boolean.toString(req.isSecure()); + } + resp.getOutputStream().println(returnValue); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/resources/project-stages.yml b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/resources/project-stages.yml new file mode 100644 index 0000000..e33af84 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/resources/project-stages.yml @@ -0,0 +1,10 @@ +swarm: + http: + keystore: + path: /ssl/keystore + password: password + key: + password: password + certificate: + # SWARM-1040 + alias: wildfly-swarm-ssl diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/webapp/WEB-INF/web.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..7fd775c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/ssl/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/pom.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/pom.xml new file mode 100644 index 0000000..f5ac6aa --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/pom.xml @@ -0,0 +1,127 @@ + + + + 4.0.0 + + + com.redhat.qe.openjdk + parent-msa-wildfly-swarm + 2.0.0-SNAPSHOT + ../parent-msa-wildfly-swarm + + + sti-wildfly-swarm + WildFly Swarm HelloWorld Sample + WildFly Swarm HelloWorld Sample + war + + + **/Broken*.java + + + + + io.thorntail + cdi + + + io.thorntail + undertow + + + junit + junit + 4.12 + test + + + + + sti + + + + + + maven-compiler-plugin + ${maven.compiler.version} + + + ${qe.openjdk.broken.file} + + + + + + + + + io.thorntail + thorntail-maven-plugin + ${thorntail.version} + + + + package + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + ${qe.openjdk.test.fail} + + + + + + + + + openshift + + + broken-deps + + + broken-repository + http://broken.repo + + true + + + false + + + + + + broken-group + broken-artifact + 1.0.0.Final + + + + + fail-test + + true + + + + compile-error + + Ignore + + + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/BrokenService.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/BrokenService.java new file mode 100644 index 0000000..968794c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/BrokenService.java @@ -0,0 +1,10 @@ +package com.redhat.qe.openjdk.swarm.sti; + +/** + * Its needed for STI tests + */ +public class BrokenService { + + public String sayHello(String name) { + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/HelloWorldService.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/HelloWorldService.java new file mode 100644 index 0000000..9c73a01 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/HelloWorldService.java @@ -0,0 +1,12 @@ +package com.redhat.qe.openjdk.swarm.sti; + +import javax.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class HelloWorldService { + + public String getHelloMessage(String name) { + return "Initial " + name; + } + +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/HelloWorldServlet.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/HelloWorldServlet.java new file mode 100644 index 0000000..a4b549e --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/HelloWorldServlet.java @@ -0,0 +1,22 @@ +package com.redhat.qe.openjdk.swarm.sti; + +import javax.inject.Inject; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/HelloWorld") +public class HelloWorldServlet extends HttpServlet { + @Inject + private HelloWorldService helloWorldService; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String name = req.getParameter("name"); + resp.getWriter().println(helloWorldService.getHelloMessage(name)); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/PingServlet.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/PingServlet.java new file mode 100644 index 0000000..ee9438b --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/java/com/redhat/qe/openjdk/swarm/sti/PingServlet.java @@ -0,0 +1,19 @@ +package com.redhat.qe.openjdk.swarm.sti; + +import javax.inject.Inject; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/ping") +public class PingServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.getWriter().println("pong"); + } +} diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/webapp/WEB-INF/web.xml b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..7fd775c --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + diff --git a/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/test/java/com/redhat/qe/openjdk/swarm/sti/ShouldFailTest.java b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/test/java/com/redhat/qe/openjdk/swarm/sti/ShouldFailTest.java new file mode 100644 index 0000000..33b0e54 --- /dev/null +++ b/test-openjdk/src/test/resources/apps/wildfly-swarm/sti/src/test/java/com/redhat/qe/openjdk/swarm/sti/ShouldFailTest.java @@ -0,0 +1,14 @@ +package com.redhat.qe.openjdk.swarm.sti; + +import org.junit.Assert; +import org.junit.Test; + +public class ShouldFailTest { + + @Test + public void shouldFailTest() { + if ("true".equals(System.getProperty("qe.openjdk.test.fail", "false"))) { + Assert.fail("Failed upon request"); + } + } +} diff --git a/test-openjdk/src/test/resources/log4j2.yaml b/test-openjdk/src/test/resources/log4j2.yaml new file mode 100644 index 0000000..ea8903e --- /dev/null +++ b/test-openjdk/src/test/resources/log4j2.yaml @@ -0,0 +1,15 @@ +Configuration: + status: info + + Appenders: + Console: + name: Console + target: SYSTEM_OUT + PatternLayout: + Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" + + Loggers: + Root: + level: trace + AppenderRef: + ref: Console diff --git a/test-openjdk/src/test/resources/logback.xml b/test-openjdk/src/test/resources/logback.xml new file mode 100644 index 0000000..358f043 --- /dev/null +++ b/test-openjdk/src/test/resources/logback.xml @@ -0,0 +1,59 @@ + + + + + + + INFO + + + [%d] %-5p- %m%n + + + + 300 + + + + + log/test.log + false + + DEBUG + + + [%d] %-5p- %m%n + + + + 300 + + + + + log/everything.log + false + + [%d] %-5p- %m%n + + + + 300 + + + + + + + + + + + + + + + + + + \ No newline at end of file