diff --git a/modules/jlink/artifacts/opt/jboss/container/java/jlink/generatejdkdeps.sh b/modules/jlink/artifacts/opt/jboss/container/java/jlink/generatejdkdeps.sh new file mode 100755 index 00000000..c7a1fe40 --- /dev/null +++ b/modules/jlink/artifacts/opt/jboss/container/java/jlink/generatejdkdeps.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +function generatejdkdeps() { + echo "Generating JDK deps" + $JAVA_HOME/bin/java --list-modules > $S2I_JLINK_TEMP_PATH/java-modules.txt + < $S2I_JLINK_TEMP_PATH/java-modules.txt sed "s/\\@.*//" > $S2I_JLINK_TEMP_PATH/modules.txt + grep -Fx -f $S2I_JLINK_TEMP_PATH/stripped-deps.txt $S2I_JLINK_TEMP_PATH/modules.txt | tr '\n' ',' | tr -d "[:space:]" > $S2I_JLINK_TEMP_PATH/module-deps.txt + echo "jdk.zipfs" >> $S2I_JLINK_TEMP_PATH/module-deps.txt +} \ No newline at end of file diff --git a/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkdeps.sh b/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkdeps.sh new file mode 100755 index 00000000..938e3db0 --- /dev/null +++ b/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkdeps.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -euo pipefail +shopt -s globstar + +function generate_deps() { + # Create a temporary directory for a module path + # This works around "Module java.xml.bind not found, required by java.ws.rs" + mkdir dependencies + + if [[ -v JAVA_LIB_DIR ]]; then + # Serially copy all library JARsinto a flat directory. Serially as we may + # have multiple libs with the same name; in which case, we clobber all but + # one rather than fail the script + find $JAVA_LIB_DIR -type f -name '*.jar' -exec cp -vt dependencies {} \; + + echo "Working with: " + echo $JAVA_APP_JAR + echo $JAVA_LIB_DIR + # generate the dependency list + $JAVA_HOME/bin/jdeps --multi-release $JAVA_VERSION -R -s \ + --module-path dependencies \ + "$JAVA_APP_JAR" \ + "$JAVA_LIB_DIR"/**/*.jar \ + > $S2I_JLINK_TEMP_PATH/deps.txt + else + $JAVA_HOME/bin/jdeps --multi-release $JAVA_VERSION -R -s \ + --module-path dependencies \ + "$JAVA_APP_JAR" \ + > $S2I_JLINK_TEMP_PATH/deps.txt + cat $S2I_JLINK_TEMP_PATH/deps.txt + fi +} diff --git a/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkjreimage.sh b/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkjreimage.sh new file mode 100755 index 00000000..7063e4e8 --- /dev/null +++ b/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkjreimage.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# TODO: Still Needed? +set -euo pipefail + +depsfile="$S2I_JLINK_TEMP_PATH/module-deps.txt" + +function generate_jre_image() { + test -f $depsfile + modules="$(cat $depsfile)" + + $JAVA_HOME/bin/jlink --output "$S2I_JLINK_OUTPUT_PATH" \ + --add-modules "$modules" \ + --strip-debug --no-header-files --no-man-pages \ + --compress=2 +} diff --git a/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkstrippeddeps.sh b/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkstrippeddeps.sh new file mode 100755 index 00000000..0f6c7e64 --- /dev/null +++ b/modules/jlink/artifacts/opt/jboss/container/java/jlink/mkstrippeddeps.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -euo pipefail + +function mkstrippeddeps() { + if [ -f "$S2I_JLINK_TEMP_PATH/deps.txt" ]; then + echo "deps exists, filtering" + < $S2I_JLINK_TEMP_PATH/deps.txt \ + grep 'java\|jdk\.' | # mostly removes target/, but also jdk8internals + sed -E "s/Warning: .*//" | #remove extraneous warnings + sed -E "s/.*-> //" | # remove src of src -> dep + sed -E "s/.*\.jar//" | # remove extraneous dependencies + sed "s#/.*##" | # delete anything after a slash. in practice target/.. + sort | uniq | + tee $S2I_JLINK_TEMP_PATH/stripped-deps.txt + echo "Stripping dependencies complete" + else + echo "deps does not exist" + fi +} diff --git a/modules/jlink/artifacts/opt/jboss/container/java/jlink/preflight.sh b/modules/jlink/artifacts/opt/jboss/container/java/jlink/preflight.sh new file mode 100644 index 00000000..67154d01 --- /dev/null +++ b/modules/jlink/artifacts/opt/jboss/container/java/jlink/preflight.sh @@ -0,0 +1,25 @@ +jlink_techpreview_warning() +{ + { + echo "WARNING WARNING WARNING" + echo " Jlink integration is a Tech Preview feature!" + echo " See " + echo " for more information." + echo "WARNING WARNING WARNING" + } >&2 +} + +jlink_preflight_check() +{ + # preflight check: do we have what we need? + if [ "$JAVA_VERSION" -lt 11 ]; then + echo "Jlink integration not available for JDK${JAVA_VERSION}!" + echo "Jlink integration is only supported for JDK versions 11 and newer." + exit 1 + fi + if [ ! -d /usr/lib/jvm/java/jmods ]; then + echo "Jlink integration requires the jmods RPM to be installed in the builder image, e.g." + echo " microdnf install -y java-${JAVA_VERSION}-openjdk-jmods" + exit 1 + fi +} diff --git a/modules/jlink/configure.sh b/modules/jlink/configure.sh new file mode 100644 index 00000000..5b714662 --- /dev/null +++ b/modules/jlink/configure.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Configure module +set -e + +SCRIPT_DIR=$(dirname $0) +ARTIFACTS_DIR=${SCRIPT_DIR}/artifacts + +chown -R default:root $SCRIPT_DIR +chmod -R ug+rwX $SCRIPT_DIR +chmod ug+x ${ARTIFACTS_DIR}/opt/jboss/container/java/jlink/* + +pushd ${ARTIFACTS_DIR} +cp -pr * / +popd diff --git a/modules/jlink/module.yaml b/modules/jlink/module.yaml new file mode 100644 index 00000000..518e0fe8 --- /dev/null +++ b/modules/jlink/module.yaml @@ -0,0 +1,32 @@ +schema_version: 1 + +name: "jboss.container.java.jlink" +version: "2.0" +description: ^ + "Provides support for building custom JREs with a slimmed + down set of modules by making use of Jdeps and Jlink" + +execute: +- script: configure.sh + +envs: +- name: JBOSS_CONTAINER_JAVA_JLINK_MODULE + value: /opt/jboss/container/java/jlink +- name: S2I_JLINK_OUTPUT_PATH + value: /tmp/jre +- name: S2I_JLINK_TEMP_PATH + value: /tmp/jlink +- name: S2I_ENABLE_JLINK + description: ^ + Enables the Jdeps/JLink workflow to minimize JRE size + example: "false" + +modules: + install: + - name: jboss.container.java.run + - name: jboss.container.util.pathfinder + +packages: + install: + - binutils # for objcopy + - java-21-openjdk-jmods diff --git a/modules/jlink/tests/features/jlink.feature b/modules/jlink/tests/features/jlink.feature new file mode 100644 index 00000000..1a60593e --- /dev/null +++ b/modules/jlink/tests/features/jlink.feature @@ -0,0 +1,36 @@ +@openjdk-tech-preview/openjdk-21-jlink-rhel9 +Feature: Openshift OpenJDK S2I tests (jlink specific) + + Scenario: tech preview warning is printed (OPENJDK-3038) + Given s2i build https://github.com/rh-openjdk/openjdk-container-test-applications from spring-boot-sample-simple/target using master + | variable | value | + | S2I_ENABLE_JLINK | true | + Then s2i build log should contain Jlink integration is a Tech Preview feature + +Scenario: Ensure S2I_ENABLE_JLINK is not set to true + Given s2i build https://github.com/rh-openjdk/openjdk-container-test-applications from spring-boot-sample-simple/target using master + Then s2i build log should not contain Jlink integration is a Tech Preview feature + And file /tmp/jre should not exist + +Scenario: Check that /tmp/jre/bin/java and /tmp/jre/lib/modules exist post s2i build if jlink is enabled. + Given s2i build https://github.com/rh-openjdk/openjdk-container-test-applications from quarkus-quickstarts/getting-started-3.9.2-uberjar + | variable | value | + | S2I_ENABLE_JLINK | true | + Then file /tmp/jre/bin/java should exist and be a file + And file /tmp/jre/lib/modules should exist and be a file + +Scenario: Check that /tmp/jlink is deleted when S2I_DELETE_SOURCE is set + Given s2i build https://github.com/rh-openjdk/openjdk-container-test-applications from quarkus-quickstarts/getting-started-3.9.2-uberjar + | variable | value | + | S2I_ENABLE_JLINK | true | + | S2I_DELETE_SOURCE | true | + Then s2i build log should contain Cleaning up temporary file directory /tmp/jlink + And file /tmp/jlink should not exist + +Scenario: Check that /tmp/jlink is not deleted when S2I_DELETE_SOURCE is set to false + Given s2i build https://github.com/rh-openjdk/openjdk-container-test-applications from quarkus-quickstarts/getting-started-3.9.2-uberjar + | variable | value | + | S2I_ENABLE_JLINK | true | + | S2I_DELETE_SOURCE | false | + Then s2i build log should not contain Cleaning up temporary file directory /tmp/jlink + And file /tmp/jlink should exist \ No newline at end of file diff --git a/modules/jvm/tests/features/memory.feature b/modules/jvm/tests/features/memory.feature index 53cd373a..8b5f465d 100644 --- a/modules/jvm/tests/features/memory.feature +++ b/modules/jvm/tests/features/memory.feature @@ -36,6 +36,7 @@ Feature: OPENJDK-559 JVM Memory tests @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 + @openjdk-tech-preview/openjdk-21-jlink-rhel9 Scenario: Ensure Maven doesn't use MaxRAMPercentage=80 Given s2i build https://github.com/rh-openjdk/openjdk-container-test-applications.git from spring-boot-sample-simple Then s2i build log should match regex INFO Using MAVEN_OPTS.*-XX:MaxRAMPercentage=25.0$ diff --git a/modules/jvm/tests/features/runtime.feature b/modules/jvm/tests/features/runtime.feature index fcd338d3..86aabf1f 100644 --- a/modules/jvm/tests/features/runtime.feature +++ b/modules/jvm/tests/features/runtime.feature @@ -1,6 +1,7 @@ @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 +@openjdk-tech-preview/openjdk-21-jlink-rhel9 Feature: Openshift OpenJDK Runtime tests @ubi9 diff --git a/modules/maven/s2i/tests/features/java_s2i.feature b/modules/maven/s2i/tests/features/java_s2i.feature index 6e3c69c2..dc2d089f 100644 --- a/modules/maven/s2i/tests/features/java_s2i.feature +++ b/modules/maven/s2i/tests/features/java_s2i.feature @@ -3,6 +3,7 @@ @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 +@openjdk-tech-preview/openjdk-21-jlink-rhel9 Feature: Openshift OpenJDK S2I tests # NOTE: these tests should be usable with the other images once we have refactored the JDK scripts. # These builds do not actually run maven. This is important, because the proxy diff --git a/modules/maven/s2i/tests/features/java_s2i_inc.feature b/modules/maven/s2i/tests/features/java_s2i_inc.feature index c1415cab..baf8c342 100644 --- a/modules/maven/s2i/tests/features/java_s2i_inc.feature +++ b/modules/maven/s2i/tests/features/java_s2i_inc.feature @@ -1,6 +1,7 @@ @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 +@openjdk-tech-preview/openjdk-21-jlink-rhel9 Feature: Openshift OpenJDK S2I tests # test incremental builds diff --git a/modules/run/artifacts/opt/jboss/container/java/run/run-java.sh b/modules/run/artifacts/opt/jboss/container/java/run/run-java.sh index 21720628..1d2d8fce 100755 --- a/modules/run/artifacts/opt/jboss/container/java/run/run-java.sh +++ b/modules/run/artifacts/opt/jboss/container/java/run/run-java.sh @@ -5,6 +5,7 @@ set -eo pipefail export JBOSS_CONTAINER_UTIL_LOGGING_MODULE="${JBOSS_CONTAINER_UTIL_LOGGING_MODULE-/opt/jboss/container/util/logging}" export JBOSS_CONTAINER_JAVA_RUN_MODULE="${JBOSS_CONTAINER_JAVA_RUN_MODULE-/opt/jboss/container/java/run}" +export JBOSS_CONTAINER_UTIL_PATHFINDER_MODULE="${JBOSS_CONTAINER_UTIL_PATHFINDER_MODULE-/opt/jboss/container/util/pathfinder}" # Default the application dir to the S2I deployment dir if [ -z "$JAVA_APP_DIR" ] @@ -12,6 +13,7 @@ if [ -z "$JAVA_APP_DIR" ] fi source "$JBOSS_CONTAINER_UTIL_LOGGING_MODULE/logging.sh" +source "$JBOSS_CONTAINER_UTIL_PATHFINDER_MODULE/pathfinder.sh" # ========================================================== # Generic run script for running arbitrary Java applications @@ -30,99 +32,6 @@ check_error() { fi } -# detect Quarkus fast-jar package type (OPENJDK-631) -is_quarkus_fast_jar() { - if test -f quarkus-app/quarkus-run.jar; then - log_info "quarkus fast-jar package type detected" - echo quarkus-app/quarkus-run.jar - return 0 - else - return 1 - fi -} - -# Try hard to find a sane default jar-file -auto_detect_jar_file() { - local dir=$1 - - # Filter out temporary jars from the shade plugin which start with 'original-' - local old_dir=$(pwd) - cd ${dir} - if [ $? = 0 ]; then - - if quarkus="$(is_quarkus_fast_jar)"; then - echo "$quarkus" - return - fi - - local nr_jars=`ls *.jar 2>/dev/null | grep -v '^original-' | wc -l | tr -d '[[:space:]]'` - if [ ${nr_jars} = 1 ]; then - ls *.jar | grep -v '^original-' - exit 0 - fi - - log_error "Neither \$JAVA_MAIN_CLASS nor \$JAVA_APP_JAR is set and ${nr_jars} JARs found in ${dir} (1 expected)" - cd ${old_dir} - else - log_error "No directory ${dir} found for auto detection" - fi -} - -# Check directories (arg 2...n) for a jar file (arg 1) -get_jar_file() { - local jar=$1 - shift; - - if [ "${jar:0:1}" = "/" ]; then - if [ -f "${jar}" ]; then - echo "${jar}" - else - log_error "No such file ${jar}" - fi - else - for dir in $*; do - if [ -f "${dir}/$jar" ]; then - echo "${dir}/$jar" - return - fi - done - log_error "No ${jar} found in $*" - fi -} - -load_env() { - # Configuration stuff is read from this file - local run_env_sh="run-env.sh" - - # Load default default config - if [ -f "${JBOSS_CONTAINER_JAVA_RUN_MODULE}/${run_env_sh}" ]; then - source "${JBOSS_CONTAINER_JAVA_RUN_MODULE}/${run_env_sh}" - fi - - # Check also $JAVA_APP_DIR. Overrides other defaults - # It's valid to set the app dir in the default script - if [ -f "${JAVA_APP_DIR}/${run_env_sh}" ]; then - source "${JAVA_APP_DIR}/${run_env_sh}" - fi - - export JAVA_APP_DIR - - # JAVA_LIB_DIR defaults to JAVA_APP_DIR - export JAVA_LIB_DIR="${JAVA_LIB_DIR:-${JAVA_APP_DIR}}" - if [ -z "${JAVA_MAIN_CLASS}" ] && [ -z "${JAVA_APP_JAR}" ]; then - JAVA_APP_JAR="$(auto_detect_jar_file ${JAVA_APP_DIR})" - check_error "${JAVA_APP_JAR}" - fi - - if [ "x${JAVA_APP_JAR}" != x ]; then - local jar="$(get_jar_file ${JAVA_APP_JAR} ${JAVA_APP_DIR} ${JAVA_LIB_DIR})" - check_error "${jar}" - export JAVA_APP_JAR=${jar} - else - export JAVA_MAIN_CLASS - fi -} - # Combine all java options get_java_options() { local jvm_opts @@ -226,7 +135,8 @@ mask_passwords() { # Start JVM startup() { # Initialize environment - load_env + # populates JAVA_APP_JAR and JAVA_LIB_DIR and possibly JAVA_MAIN_CLASS + setup_java_app_and_lib local args cd ${JAVA_APP_DIR} diff --git a/modules/run/module.yaml b/modules/run/module.yaml index 249e85eb..700dfe2f 100644 --- a/modules/run/module.yaml +++ b/modules/run/module.yaml @@ -59,3 +59,4 @@ modules: - name: jboss.container.user - name: jboss.container.java.jvm - name: jboss.container.util.logging + - name: jboss.container.util.pathfinder diff --git a/modules/run/tests/features/java.security.feature b/modules/run/tests/features/java.security.feature index 9d48c16c..e335c516 100644 --- a/modules/run/tests/features/java.security.feature +++ b/modules/run/tests/features/java.security.feature @@ -1,6 +1,7 @@ @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 +@openjdk-tech-preview/openjdk-21-jlink-rhel9 Feature: Openshift S2I tests Scenario: Check networkaddress.cache.negative.ttl has been set correctly Given s2i build https://github.com/rh-openjdk/openjdk-container-test-applications.git from binary-cli-security-property diff --git a/modules/s2i/bash/artifacts/usr/local/s2i/assemble b/modules/s2i/bash/artifacts/usr/local/s2i/assemble index fa5e0f20..66190688 100644 --- a/modules/s2i/bash/artifacts/usr/local/s2i/assemble +++ b/modules/s2i/bash/artifacts/usr/local/s2i/assemble @@ -1,6 +1,6 @@ #!/bin/sh -set -e +set -eo pipefail source "${JBOSS_CONTAINER_UTIL_LOGGING_MODULE}/logging.sh" source "${JBOSS_CONTAINER_MAVEN_S2I_MODULE}/maven-s2i" @@ -14,3 +14,55 @@ source "${JBOSS_CONTAINER_JAVA_S2I_MODULE}/maven-s2i-overrides" # invoke the build maven_s2i_build +# run the pathfinder scripts to define JAVA_APP_JAR and JAVA_LIB_DIR +source "${JBOSS_CONTAINER_UTIL_PATHFINDER_MODULE}/pathfinder.sh" +setup_java_app_and_lib + +# include our jlink scripts +if [ "$S2I_ENABLE_JLINK" = "true" ]; then + + source "${JBOSS_CONTAINER_JAVA_JLINK_MODULE}/preflight.sh" + jlink_techpreview_warning + jlink_preflight_check + + if [ ! -d "${S2I_JLINK_TEMP_PATH}" ]; then + log_info "S2I_JLINK_TEMP_PATH does not exist, creating ${S2I_JLINK_TEMP_PATH}" + mkdir -pm 775 "${S2I_JLINK_TEMP_PATH}" + fi + + source "${JBOSS_CONTAINER_JAVA_JLINK_MODULE}/mkdeps.sh" + echo "Invoking mkdeps" + generate_deps || { + log_error "mkdeps failed, return code: $?" + exit 1 + } + + source "${JBOSS_CONTAINER_JAVA_JLINK_MODULE}/mkstrippeddeps.sh" + echo "Stripping dependencies" + mkstrippeddeps || { + log_error "stripping dependencies failed, return code: $?" + exit 1 + } + + source "${JBOSS_CONTAINER_JAVA_JLINK_MODULE}/generatejdkdeps.sh" + echo "Generating JDK dependencies" + generatejdkdeps || { + log_error "generating JDK dependencies failed, return code: $?" + exit 1 + } + + source "${JBOSS_CONTAINER_JAVA_JLINK_MODULE}/mkjreimage.sh" + echo "Linking jre" + generate_jre_image || { + log_error "Linking JRE failed, return code: $?" + exit 1 + } + + if [ "$S2I_DELETE_SOURCE" == "true" ]; then + if [ -n "$(find $S2I_JLINK_TEMP_PATH -maxdepth 0 -type d ! -empty 2> /dev/null)" ]; then + log_info "Cleaning up temporary file directory $S2I_JLINK_TEMP_PATH" + rm -rf $S2I_JLINK_TEMP_PATH + fi + fi +fi + diff --git a/modules/s2i/bash/module.yaml b/modules/s2i/bash/module.yaml index ffcfbc0b..fb70b2a6 100644 --- a/modules/s2i/bash/module.yaml +++ b/modules/s2i/bash/module.yaml @@ -16,6 +16,7 @@ modules: - name: jboss.container.maven.s2i - name: jboss.container.java.run - name: jboss.container.util.logging + - name: jboss.container.util.pathfinder - name: jboss.container.s2i.core packages: diff --git a/modules/s2i/core/artifacts/opt/jboss/container/s2i/core/s2i-core b/modules/s2i/core/artifacts/opt/jboss/container/s2i/core/s2i-core index 47446df2..c02d7968 100644 --- a/modules/s2i/core/artifacts/opt/jboss/container/s2i/core/s2i-core +++ b/modules/s2i/core/artifacts/opt/jboss/container/s2i/core/s2i-core @@ -33,6 +33,7 @@ function s2i_core_env_init() { S2I_IMAGE_SOURCE_MOUNTS="${S2I_IMAGE_SOURCE_MOUNTS:-${CUSTOM_INSTALL_DIRECTORIES}}" S2I_ENABLE_INCREMENTAL_BUILDS="${S2I_ENABLE_INCREMENTAL_BUILDS:-true}" S2I_DELETE_SOURCE="${S2I_DELETE_SOURCE:-true}" + S2I_ENABLE_JLINK="${S2I_ENABLE_JLINK:-false}" } # extensions may override this method to initialize environment variables diff --git a/modules/s2i/core/tests/features/java_s2i_quarkus.feature b/modules/s2i/core/tests/features/java_s2i_quarkus.feature index 7ab04b5e..1a14f093 100644 --- a/modules/s2i/core/tests/features/java_s2i_quarkus.feature +++ b/modules/s2i/core/tests/features/java_s2i_quarkus.feature @@ -2,6 +2,7 @@ @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 +@openjdk-tech-preview/openjdk-21-jlink-rhel9 Feature: Openshift OpenJDK S2I tests (Quarkus-based) Scenario: Ensure Quarkus CDS doesn't fail due to timestamp mismatch (OPENDJK-1673) diff --git a/modules/s2i/core/tests/features/s2i-core.feature b/modules/s2i/core/tests/features/s2i-core.feature index b247bfe9..c2be89b1 100644 --- a/modules/s2i/core/tests/features/s2i-core.feature +++ b/modules/s2i/core/tests/features/s2i-core.feature @@ -1,6 +1,7 @@ @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 +@openjdk-tech-preview/openjdk-21-jlink-rhel9 Feature: Openshift S2I tests # OPENJDK-84 - /tmp/src should not be present after build Scenario: run an s2i build and check that /tmp/src has been removed afterwards diff --git a/modules/util/pathfinder/artifacts/opt/jboss/container/util/pathfinder/pathfinder.sh b/modules/util/pathfinder/artifacts/opt/jboss/container/util/pathfinder/pathfinder.sh new file mode 100644 index 00000000..3f4e0f4b --- /dev/null +++ b/modules/util/pathfinder/artifacts/opt/jboss/container/util/pathfinder/pathfinder.sh @@ -0,0 +1,96 @@ +# Error is indicated with a prefix in the return value +check_error() { + local msg=$1 + if echo ${msg} | grep -q "^ERROR:"; then + log_error ${msg} + exit 1 + fi +} + +# detect Quarkus fast-jar package type (OPENJDK-631) +is_quarkus_fast_jar() { + if test -f quarkus-app/quarkus-run.jar; then + log_info "quarkus fast-jar package type detected" + echo quarkus-app/quarkus-run.jar + return 0 + else + return 1 + fi +} + +# Try hard to find a sane default jar-file +auto_detect_jar_file() { + local dir=$1 + + # Filter out temporary jars from the shade plugin which start with 'original-' + local old_dir=$(pwd) + cd ${dir} + if [ $? = 0 ]; then + if quarkus="$(is_quarkus_fast_jar)"; then + echo "$quarkus" + return + fi + local nr_jars=`ls *.jar 2>/dev/null | grep -v '^original-' | wc -l | tr -d '[[:space:]]'` + if [ ${nr_jars} = 1 ]; then + ls *.jar | grep -v '^original-' + exit 0 + fi + + log_error "Neither \$JAVA_MAIN_CLASS nor \$JAVA_APP_JAR is set and ${nr_jars} JARs found in ${dir} (1 expected)" + cd ${old_dir} + else + log_error "No directory ${dir} found for auto detection" + fi +} + +# Check directories (arg 2...n) for a jar file (arg 1) +get_jar_file() { + local jar=$1 + shift; + + if [ "${jar:0:1}" = "/" ]; then + if [ -f "${jar}" ]; then + echo "${jar}" + else + log_error "No such file ${jar}" + fi + else + for dir in $*; do + if [ -f "${dir}/$jar" ]; then + echo "${dir}/$jar" + return + fi + done + log_error "No ${jar} found in $*" + fi +} + +setup_java_app_and_lib() { + # Default the application dir to the S2I deployment dir + if [ -z "$JAVA_APP_DIR" ] + then JAVA_APP_DIR=/deployments + fi + + # application-source provided shell script that may set environment + # variables + if [ -f "${JAVA_APP_DIR}/run-env.sh" ]; then + source "${JAVA_APP_DIR}/run-env.sh" + fi + + export JAVA_APP_DIR + + # JAVA_LIB_DIR defaults to JAVA_APP_DIR + export JAVA_LIB_DIR="${JAVA_LIB_DIR:-${JAVA_APP_DIR}}" + if [ -z "${JAVA_MAIN_CLASS}" ] && [ -z "${JAVA_APP_JAR}" ]; then + JAVA_APP_JAR="$(auto_detect_jar_file ${JAVA_APP_DIR})" + check_error "${JAVA_APP_JAR}" + fi + + if [ "x${JAVA_APP_JAR}" != x ]; then + local jar="$(get_jar_file ${JAVA_APP_JAR} ${JAVA_APP_DIR} ${JAVA_LIB_DIR})" + check_error "${jar}" + export JAVA_APP_JAR=${jar} + else + export JAVA_MAIN_CLASS + fi +} diff --git a/modules/util/pathfinder/configure.sh b/modules/util/pathfinder/configure.sh new file mode 100644 index 00000000..94810789 --- /dev/null +++ b/modules/util/pathfinder/configure.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -euo pipefail + +SCRIPT_DIR=$(dirname $0) +ARTIFACTS_DIR=${SCRIPT_DIR}/artifacts + +install -m 0644 -D {${ARTIFACTS_DIR},}/opt/jboss/container/util/pathfinder/pathfinder.sh diff --git a/modules/util/pathfinder/module.yaml b/modules/util/pathfinder/module.yaml new file mode 100644 index 00000000..de74802d --- /dev/null +++ b/modules/util/pathfinder/module.yaml @@ -0,0 +1,34 @@ +schema_version: 1 + +name: "jboss.container.util.pathfinder" +version: "1.0" +description: ^ + "Provides support for determining Java application jar locations + as well as library directories" + +envs: +- name: JBOSS_CONTAINER_UTIL_PATHFINDER_MODULE + value: /opt/jboss/container/util/pathfinder + +- name: JAVA_APP_DIR + description: ^ + The directory where the application resides. All paths in your application + are relative to this directory. + example: "myapplication/" + +- name: JAVA_MAIN_CLASS + description: ^ + A main class to use as argument for `java`. When this environment variable + is given, all jar files in **JAVA_APP_DIR** are added to the classpath as + well as **JAVA_LIB_DIR**. + example: "com.example.MainClass" + +- name: JAVA_LIB_DIR + description: ^ + Directory holding the Java jar files as well an optional `classpath` file + which holds the classpath. Either as a single line classpath (colon + separated) or with jar files listed line-by-line. If not set + **JAVA_LIB_DIR** is the same as **JAVA_APP_DIR**. + +execute: +- script: configure.sh \ No newline at end of file diff --git a/openjdk-21-jlink-rhel9.yaml b/openjdk-21-jlink-rhel9.yaml new file mode 100644 index 00000000..e69ae665 --- /dev/null +++ b/openjdk-21-jlink-rhel9.yaml @@ -0,0 +1,64 @@ +# This is an Image descriptor for Cekit + +schema_version: 1 + +from: "registry.access.redhat.com/ubi9/ubi-minimal" +name: &name "openjdk-tech-preview/openjdk-21-jlink-rhel9" +version: &version "1.23" +description: "Source To Image (S2I) image for Red Hat OpenShift providing OpenJDK 21" + +labels: +- name: "io.k8s.description" + value: "Platform for building and running plain Java applications (fat-jar and flat classpath)" +- name: "io.k8s.display-name" + value: "Java Applications" +- name: "io.openshift.tags" + value: "builder,java" +- name: "maintainer" + value: "Red Hat OpenJDK " +- name: "com.redhat.component" + value: "openjdk-21-jlink-tech-preview-ubi9-container" +- name: "usage" + value: &docs "https://rh-openjdk.github.io/redhat-openjdk-containers/" +- name: "com.redhat.license_terms" + value: "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI" +- name: "org.opencontainers.image.documentation" + value: *docs +- name: "name" + value: *name +- name: "version" + value: *version + +envs: +- name: PATH + value: $PATH:"/usr/local/s2i" +- name: "JBOSS_IMAGE_NAME" + value: *name +- name: "JBOSS_IMAGE_VERSION" + value: *version +- name: "LANG" + value: "C.utf8" + +ports: +- value: 8080 +- value: 8443 + +modules: + repositories: + - path: modules + install: + - name: jboss.container.util.pkg-update + - name: jboss.container.openjdk.jdk + version: "21" + - name: jboss.container.maven + version: "3.9.21" + - name: jboss.container.util.tzdata + - name: jboss.container.java.s2i.bash + - name: jboss.container.util.tzdata + - name: jboss.container.java.jlink + +help: + add: true + +packages: + manager: microdnf diff --git a/redhat/openjdk-21-jlink-rhel9.yaml b/redhat/openjdk-21-jlink-rhel9.yaml new file mode 100644 index 00000000..3df38266 --- /dev/null +++ b/redhat/openjdk-21-jlink-rhel9.yaml @@ -0,0 +1,33 @@ +# This OSBS Base Image is designed and engineered to be the base layer for +# Red Hat products. This base image is only supported for approved Red Hat +# products. This image is maintained by Red Hat and updated regularly. +from: registry.redhat.io/rhel9-osbs/osbs-ubi9-minimal +osbs: + configuration: + container: + compose: + pulp_repos: true + packages: + - java-21-openjdk + - java-21-openjdk-devel + - java-21-openjdk-headless + signing_intent: release + repository: + name: containers/openjdk + branch: openjdk-21-jlink-tech-preview-ubi9 + +packages: + manager: microdnf + content_sets: + x86_64: + - rhel-9-for-x86_64-baseos-rpms + - rhel-9-for-x86_64-appstream-rpms + ppc64le: + - rhel-9-for-ppc64le-baseos-rpms + - rhel-9-for-ppc64le-appstream-rpms + aarch64: + - rhel-9-for-aarch64-baseos-rpms + - rhel-9-for-aarch64-appstream-rpms + s390x: + - rhel-9-for-s390x-baseos-rpms + - rhel-9-for-s390x-appstream-rpms diff --git a/templates/jlink/README.md b/templates/jlink/README.md new file mode 100644 index 00000000..3eb9fd52 --- /dev/null +++ b/templates/jlink/README.md @@ -0,0 +1,125 @@ +# OpenShift Jlink integration (Tech Preview) + +To try it out, +you need: + +1. Access to an OpenShift instance, such as [OpenShift Local](https://developers.redhat.com/products/openshift-local/overview) +2. UBI9 OpenJDK ImageStreams that include `jlink-dev` changes (see below) +3. The template [jlinked-app.yaml](jlinked-app.yaml). + +DISCLAIMER: This template requires OpenShift to be able to resolve ImageStreams, as such it can only be used in projects where the openshift.io/run-level label set to 0 or 1. This means it cannot be used with default, kube-public, kube-system, openshift, openshift-infra, openshift-node, and other system-created projects. + +## Stage 0: UBI9 OpenJDK ImageStreams with jlink-dev changes + +Whilst the `jlink-dev` feature is in Tech Preview, we must prepare separate +UBI9 OpenJDK ImageStreams with `jlink-dev` support. + +1. Pull the Tech-Preview image + + podman pull registry.access.redhat.com/openjdk-tech-preview/openjdk-21-jlink-rhel9:latest + podman tag registry.access.redhat.com/openjdk-tech-preview/openjdk-21-jlink-rhel9:latest \ + openjdk-tech-preview/openjdk-21-jlink-rhel9:latest + +OR + +1. Build a suitable OpenJDK container image from [this + repository](https://github.com/jboss-container-images/openjdk), + branch `jlink-dev`. e.g. + + cekit --descriptor ubi9-openjdk-21.yaml build podman + +2. Create an OpenShift project + + oc new-project $PROJECT + +3. Within your OpenShift project, + + oc create imagestream openjdk-21-jlink-tech-preview + +4. You may need to configure your container engine to not TLS-verify the OpenShift + registry. For Docker, add the following to `/etc/docker/daemon.json` and restart + the daemon: + + { + "insecure-registries": [ "default-route-openshift-image-registry.apps-crc.testing" ] + } + + For podman, add the following to `~/.config/containers/registries.conf`: + + [[registry]] + location = "default-route-openshift-image-registry.apps-crc.testing" + insecure = true + +5. Log into the OpenShift registry, e.g. + + REGISTRY_AUTH_PREFERENCE=docker oc registry login + + or + + oc registry login + +6. tag and push the dev image into it. The OpenShift console gives you the + exact URI for your instance + + podman tag openjdk-tech-preview/openjdk-21-jlink-rhel9:latest default-route-openshift-image-registry.apps-crc.testing/$PROJECT/openjdk-21-jlink-tech-preview:latest + podman push default-route-openshift-image-registry.apps-crc.testing/$PROJECT/openjdk-21-jlink-tech-preview:latest + +## Stage 1: Load the template into OpenShift and instantiate it + +Create an OpenShift template `templates/jlink-app-template` from the jlinked-app template file + + oc create -f templates/jlink/jlinked-app.yaml + +Process it to create the needed objects. You can list the parameters using + + oc process --parameters jlink-app-template + +Some suitable test values for the parameters are + + * JDK_VERSION: 21 + * APP_URI: https://github.com/rh-openjdk/openjdk-container-test-applications + * REF: master + * CONTEXT_DIR: quarkus-quickstarts/getting-started-3.21.2-uberjar + * APPNAME: quarkus-quickstart + * TARGET_PORT: 8080 + * SERVICE_PORT: 8080 + + oc process \ + -p JDK_VERSION=21 \ + -p APP_URI=https://github.com/rh-openjdk/openjdk-container-test-applications \ + -p REF=master \ + -p CONTEXT_DIR=quarkus-quickstarts/getting-started-3.21.2-uberjar \ + -p APPNAME=quarkus-quickstart \ + -p TARGET_PORT=8080 \ + -p SERVICE_PORT=8080 \ + templates/jlink-app-template \ + | oc create -f - + +## Stage 2: Observe the results + +See all the OpenShift objects that were created: + + oc get all + +## Stage 3: Kick off builds + +Instantiating the template will cause 3 separate BuildConfigs to be created and will automatically start their builds in sequence: + +1. $APPNAME-jlink-builder-jdk-$JDK_VERSION +2. $APPNAME-jlink-s2i-jdk-$JDK_VERSION +3. $APPNAME-multistage-buildconfig + +Where $APPNAME and $JDK_VERSION are the paremeters initially passed to the template. + +A build will automatically start for (1). Once complete, builds for (2) and (3) should be automatically triggered in sequence. + +## Stage 4: create deployment + +The ImageStreamTag `$APPNAME-lightweight-image:latest` will be populated with the new application container image. + +Create a deployment to see it work. E.g., in the Developer Perspective, select +"+Add", "Container Images", "Image stream tag from internal registry", ..., +"Create" + +Then from "Topology", select the "Open URL" icon to open the newly deployed +App. diff --git a/templates/jlink/jlinked-app.yaml b/templates/jlink/jlinked-app.yaml new file mode 100644 index 00000000..79b200af --- /dev/null +++ b/templates/jlink/jlinked-app.yaml @@ -0,0 +1,307 @@ +--- +apiVersion: template.openshift.io/v1 +kind: Template +metadata: + annotations: + description: Template to produce imagestreams and buildconfigs for jlinked application + name: jlink-app-template +############################################################################## +# List of parameters required to create template +parameters: +- description: JDK version to produce a jmods image and imagestream for + name: JDK_VERSION + value: "21" + required: true +- description: OpenJDK builder image version tag + name: BUILDER_IMAGE_TAG + value: "latest" +- description: A name for the application used to ensure created resources are uniquely named + name: APPNAME + required: true +- description: Application to run the jlink workflow on + name: APP_URI + required: true +- description: Git Ref to run the jlink workflow on + name: REF + required: true +- description: Context Dir to use for the jlink workflow + name: CONTEXT_DIR + required: true +- description: A secret string used to configure the GitHub webhook + name: GITHUB_WEBHOOK_SECRET + generate: expression + from: "[a-zA-Z0-9]{16}" + required: true +- description: Target port for the created Route + name: TARGET_PORT + value: "8080" + required: true +- description: Port for the created Service to listen on + name: SERVICE_PORT + value: "8181" + required: true +message: "... The GitHub webhook secret is ${GITHUB_WEBHOOK_SECRET} ..." +############################################################################## +# Following are the objects(imagestream and buildconfigs) for all the 3-stages +objects: +############################################################################## +# stage-1: Output ImageStream +- apiVersion: image.openshift.io/v1 + kind: ImageStream + metadata: + name: ${APPNAME}-openjdk-${JDK_VERSION}-jlink-tech-preview + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + lookupPolicy: + local: false +############################################################################## +# stage-1: BuildConfig +- apiVersion: build.openshift.io/v1 + kind: BuildConfig + metadata: + name: ${APPNAME}-jlink-builder-jdk-${JDK_VERSION} + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + source: + dockerfile: | + FROM - + RUN if [ ! -f "/opt/jboss/container/java/jlink/preflight.sh" ]; then echo "jlink scripts doesn't exist" 2>&1; exit 1; fi + USER 0 + RUN mkdir -p /mnt/jrootfs + RUN microdnf install --installroot /mnt/jrootfs --releasever 9 --setopt install_weak_deps=0 --nodocs -y \ + --config=/etc/dnf/dnf.conf \ + --noplugins \ + --setopt=cachedir=/var/cache \ + --setopt=reposdir=/etc/yum.repos.d \ + --setopt=varsdir=/etc/dnf/vars \ + grep gawk + RUN rm -rf /mnt/jrootfs/var/cache/* /mnt/jrootfs/var/lib/rpm /mnt/jrootfs/var/lib/dnf + USER 185 + strategy: + dockerStrategy: + from: + kind: ImageStreamTag + name: openjdk-${JDK_VERSION}-jlink-tech-preview:${BUILDER_IMAGE_TAG} # Refer README.md to create this ImageStream + output: + to: + kind: ImageStreamTag + name: ${APPNAME}-openjdk-${JDK_VERSION}-jlink-tech-preview:latest + triggers: + - type: ConfigChange + - type: ImageChange + imageChange: + from: + kind: ImageStreamTag + name: openjdk-${JDK_VERSION}-jlink-tech-preview:${BUILDER_IMAGE_TAG} +############################################################################## +# stage-2: Output ImageStream +- apiVersion: image.openshift.io/v1 + kind: ImageStream + metadata: + name: ${APPNAME}-intermediate + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + lookupPolicy: + local: false +############################################################################## +# stage-2: BuildConfig +- apiVersion: build.openshift.io/v1 + kind: BuildConfig + metadata: + name: ${APPNAME}-jlink-s2i-jdk-${JDK_VERSION} + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + source: + type: Git + git: + uri: ${APP_URI} + ref: ${REF} + contextDir: ${CONTEXT_DIR} + strategy: + sourceStrategy: + from: + kind: ImageStreamTag + name: ${APPNAME}-openjdk-${JDK_VERSION}-jlink-tech-preview:latest # Output Imagestream from stage-1 + pullPolicy: Always + env: + - name: S2I_ENABLE_JLINK + value: "true" + - name: LOGGING_SCRIPT_DEBUG + value: "true" + output: + to: + kind: ImageStreamTag + name: ${APPNAME}-intermediate:latest + triggers: + - type: ConfigChange + - type: ImageChange + imageChange: + from: + kind: ImageStreamTag + name: ${APPNAME}-openjdk-${JDK_VERSION}-jlink-tech-preview:latest # Output of stage-1 which serves as input to stage-2 + - type: GitHub + github: + secret: ${GITHUB_WEBHOOK_SECRET} + event: push +############################################################################## +# stage-3: The ubi-micro ImageStream +- apiVersion: image.openshift.io/v1 + kind: ImageStream + metadata: + name: ${APPNAME}-ubimicro + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + lookupPolicy: + local: true + tags: + - from: + kind: DockerImage + name: registry.access.redhat.com/ubi9/ubi-micro + name: latest + referencePolicy: + type: Local +############################################################################## +# stage-3: Output ImageStream +- apiVersion: image.openshift.io/v1 + kind: ImageStream + metadata: + name: ${APPNAME}-lightweight-image + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + lookupPolicy: + # Must be true for the Deployment to resolve the ImageStream + local: true +############################################################################## +# stage-3: BuildConfig +- apiVersion: build.openshift.io/v1 + kind: BuildConfig + metadata: + name: ${APPNAME}-multistage-buildconfig + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + source: + images: + - from: + kind: ImageStreamTag + name: ${APPNAME}-intermediate:latest + paths: + - sourcePath: /mnt/jrootfs + destinationDir: jrootfs + - sourcePath: /deployments + destinationDir: deployments + - sourcePath: /tmp/jre/. + destinationDir: customJVM + - sourcePath: /opt/jboss/container/. + destinationDir: runScripts + type: Dockerfile + dockerfile: | + FROM - + ARG JAVA_HOME=/usr/lib/jvm/java + + COPY jrootfs/* / + COPY deployments / + COPY customJVM ${JAVA_HOME} + COPY runScripts /opt/jboss/container/ + # these are in the micro image + RUN rm -rf /var/lib/dnf /var/lib/rpm + + ENV JAVA_HOME="${JAVA_HOME}" PATH="${JAVA_HOME}/bin:$PATH" + USER 185 + CMD /opt/jboss/container/java/run/run-java.sh + strategy: + type: Docker + dockerStrategy: + from: + kind: ImageStreamTag + name: ${APPNAME}-ubimicro:latest + output: + to: + kind: ImageStreamTag + name: ${APPNAME}-lightweight-image:latest # Tag for the final output image + triggers: + - type: ConfigChange + - type: ImageChange + imageChange: + from: + kind: ImageStreamTag + name: ${APPNAME}-intermediate:latest # output of stage-2 + - type: ImageChange + imageChange: + from: + kind: ImageStreamTag + name: ${APPNAME}-ubimicro:latest # ImageStreamTag for registry.access.redhat.com/ubi9/ubi-micro +############################################################################## +# DeploymentConfig and Route object specs +# DeploymentConfigs are discouraged, however the documentation sugggests to still +# use them if features are missing from Deployments, which in our case they are. +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: ${APPNAME}-jlinked-app-deployment + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + replicas: 1 + selector: + matchLabels: + app: ${APPNAME} + template: + metadata: + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + annotations: + # Allows Deployments to use ImageStreams + alpha.image.policy.openshift.io/resolve-names: '*' + spec: + containers: + - name: ${APPNAME}-jlinked-app-container + image: ${APPNAME}-lightweight-image:latest + ports: + - containerPort: ${{TARGET_PORT}} + protocol: TCP + strategy: + type: RollingUpdate +- apiVersion: v1 + kind: Service + metadata: + name: ${APPNAME}-jlinked-app-service + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + selector: + app: ${APPNAME} + ports: + - protocol: TCP + name: target-${TARGET_PORT}-tcp + port: ${{SERVICE_PORT}} + targetPort: ${{TARGET_PORT}} +- apiVersion: route.openshift.io/v1 + kind: Route + metadata: + name: ${APPNAME}-jlinked-app-route + labels: + app: ${APPNAME} + app.kubernetes.io/part-of: ${APPNAME} + spec: + to: + kind: Service + name: ${APPNAME}-jlinked-app-service + port: + targetPort: ${{TARGET_PORT}} diff --git a/templates/ubi9-community-image-streams.json b/templates/ubi9-community-image-streams.json new file mode 100644 index 00000000..c1de1edf --- /dev/null +++ b/templates/ubi9-community-image-streams.json @@ -0,0 +1,458 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": { + "name": "ubi9-openjdk-image-stream", + "annotations": { + "description": "ImageStream definition for Red Hat UBI9 OpenJDK.", + "openshift.io/provider-display-name": "Red Hat, Inc." + } + }, + "items": [ + { + "kind": "ImageStream", + "apiVersion": "image.openshift.io/v1", + "metadata": { + "name": "ubi9-openjdk-11", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI9)", + "openshift.io/provider-display-name": "Red Hat, Inc." + } + }, + "spec": { + "tags": [ + { + "name": "1.13", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.13" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-11:1.13" + } + }, + { + "name": "1.14", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.14" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-11:1.14" + } + }, + { + "name": "1.15", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.15" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-11:1.15" + } + }, + { + "name": "1.16", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.16" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-11:1.16" + } + }, + { + "name": "1.17", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.17" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-11:1.17" + } + }, + { + "name": "1.18", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.18" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-11:1.18" + } + } + ] + } + }, +{ + "kind": "ImageStream", + "apiVersion": "image.openshift.io/v1", + "metadata": { + "name": "ubi9-openjdk-17", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI9)", + "openshift.io/provider-display-name": "Red Hat, Inc." + } + }, + "spec": { + "tags": [ + { + "name": "1.13", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 17 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.13" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-17:1.13" + } + }, + { + "name": "1.14", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 17 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.14" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-17:1.14" + } + }, + { + "name": "1.15", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 17 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.15" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-17:1.15" + } + }, + { + "name": "1.16", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 17 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.16" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-17:1.16" + } + }, + { + "name": "1.17", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 17 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.17" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-17:1.17" + } + }, + { + "name": "1.18", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 17 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.18" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-17:1.18" + } + } + ] + } + }, +{ + "kind": "ImageStream", + "apiVersion": "image.openshift.io/v1", + "metadata": { + "name": "ubi9-openjdk-21", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 21 (UBI9)", + "openshift.io/provider-display-name": "Red Hat, Inc." + } + }, + "spec": { + "tags": [ + { + "name": "1.17", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 21 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 21 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.17" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-21:1.17" + } + }, + { + "name": "1.18", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 21 (UBI9)", + "description": "Build and run Java applications using Maven and OpenJDK 21 upon UBI9.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,ubi9", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "1.18" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi9/openjdk-21:1.18" + } + } + ] + } + }, { + "kind": "ImageStream", + "apiVersion": "image.openshift.io/v1", + "metadata": { + "name": "java", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK", + "openshift.io/provider-display-name": "Red Hat, Inc." + } + }, + "spec": { + "tags": [ + { + "name": "openjdk-8-ubi8", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 8 (UBI 8)", + "description": "Build and run Java applications using Maven and OpenJDK 1.8 upon UBI8.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk", + "supports": "java:8,java", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "8" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi8/openjdk-8:latest" + } + }, + { + "name": "8", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 8", + "description": "Build and run Java applications using Maven and OpenJDK 1.8 upon UBI8.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,hidden", + "supports": "java:8,java", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "8" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi8/openjdk-8:latest" + } + }, + { + "name": "openjdk-11-ubi8", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11 (UBI 8)", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI8.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk", + "supports": "java:11,java", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "11" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi8/openjdk-11:latest" + } + }, + { + "name": "11", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 11", + "description": "Build and run Java applications using Maven and OpenJDK 11 upon UBI8.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk,hidden", + "supports": "java:11,java", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "11" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi8/openjdk-11:latest" + } + }, + { + "name": "openjdk-17-ubi8", + "annotations": { + "openshift.io/display-name": "Red Hat OpenJDK 17 (UBI 8)", + "description": "Build and run Java applications using Maven and OpenJDK 17 upon UBI8.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk", + "supports": "java:17,java", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "17" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi8/openjdk-17:latest" + } + }, + { + "name": "latest", + "annotations": { + "openshift.io/display-name": "Java (Latest)", + "description": "Build and run Java applications using Maven.", + "iconClass": "icon-rh-openjdk", + "tags": "builder,java,openjdk", + "supports": "java", + "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts", + "sampleContextDir": "undertow-servlet", + "version": "latest" + }, + "referencePolicy": { + "type": "Local" + }, + "from": { + "kind": "ImageStreamTag", + "name": "openjdk-17-ubi8" + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/tests/features/imagebasic.feature b/tests/features/imagebasic.feature index cccff61e..d110b4e7 100644 --- a/tests/features/imagebasic.feature +++ b/tests/features/imagebasic.feature @@ -12,6 +12,7 @@ Feature: Tests for all openshift images @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 + @openjdk-tech-preview/openjdk-21-jlink-rhel9 Scenario: Check that builder labels are correctly set Given image is built Then the image should contain label io.openshift.s2i.scripts-url with value image:///usr/local/s2i diff --git a/tests/features/java/ports.feature b/tests/features/java/ports.feature index 0fa2a4a1..3079c182 100644 --- a/tests/features/java/ports.feature +++ b/tests/features/java/ports.feature @@ -1,6 +1,7 @@ @ubi9/openjdk-11 @ubi9/openjdk-17 @ubi9/openjdk-21 +@openjdk-tech-preview/openjdk-21-jlink-rhel9 Feature: Openshift OpenJDK port tests Scenario: Check ports are available diff --git a/ubi9-openjdk-17-runtime.yaml b/ubi9-openjdk-17-runtime.yaml index fdee7cea..52d2f17f 100644 --- a/ubi9-openjdk-17-runtime.yaml +++ b/ubi9-openjdk-17-runtime.yaml @@ -22,6 +22,8 @@ labels: value: &docs "https://rh-openjdk.github.io/redhat-openjdk-containers/" - name: "com.redhat.license_terms" value: "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI" +- name: "org.opencontainers.image.source" + value: "https://github.com/rh-openjdk/redhat-openjdk-containers" - name: "org.opencontainers.image.documentation" value: *docs - name: "name" diff --git a/ubi9-openjdk-17.yaml b/ubi9-openjdk-17.yaml index a701e347..ec412f02 100644 --- a/ubi9-openjdk-17.yaml +++ b/ubi9-openjdk-17.yaml @@ -22,6 +22,8 @@ labels: value: &docs "https://rh-openjdk.github.io/redhat-openjdk-containers/" - name: "com.redhat.license_terms" value: "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI" +- name: "org.opencontainers.image.source" + value: "https://github.com/rh-openjdk/redhat-openjdk-containers" - name: "org.opencontainers.image.documentation" value: *docs - name: "name"