From 87d44e6089380ff60c3f230d974bbb0a74162986 Mon Sep 17 00:00:00 2001 From: Michael Vorburger Date: Wed, 7 Nov 2018 20:56:21 +0100 Subject: [PATCH] add fedora-java8 image (#160) --- java/images.yml | 13 +- java/images/centos/Dockerfile | 2 +- java/images/fedora-java8/Dockerfile | 122 ++++ java/images/fedora-java8/README.md | 189 ++++++ ...oftware_license_version_2.0-apache-2.0.txt | 201 ++++++ java/images/fedora-java8/jolokia-opts | 94 +++ java/images/fedora-java8/licenses.css | 21 + java/images/fedora-java8/licenses.html | 43 ++ java/images/fedora-java8/licenses.xml | 41 ++ .../images/fedora-java8/prometheus-config.yml | 586 +++++++++++++++++ java/images/fedora-java8/prometheus-opts | 57 ++ java/images/fedora-java8/run-env.sh | 4 + java/images/fedora-java8/run-java.sh | 604 ++++++++++++++++++ java/images/fedora-java8/s2i/assemble | 313 +++++++++ java/images/fedora-java8/s2i/run | 61 ++ java/images/fedora-java8/s2i/s2i-setup | 6 + java/images/fedora-java8/s2i/save-artifacts | 10 + java/images/fedora-java8/s2i/usage | 2 + java/images/fedora-java8/settings.xml | 14 + java/templates/Dockerfile | 6 +- 20 files changed, 2384 insertions(+), 5 deletions(-) create mode 100644 java/images/fedora-java8/Dockerfile create mode 100644 java/images/fedora-java8/README.md create mode 100644 java/images/fedora-java8/apache_software_license_version_2.0-apache-2.0.txt create mode 100644 java/images/fedora-java8/jolokia-opts create mode 100644 java/images/fedora-java8/licenses.css create mode 100644 java/images/fedora-java8/licenses.html create mode 100644 java/images/fedora-java8/licenses.xml create mode 100644 java/images/fedora-java8/prometheus-config.yml create mode 100644 java/images/fedora-java8/prometheus-opts create mode 100644 java/images/fedora-java8/run-env.sh create mode 100644 java/images/fedora-java8/run-java.sh create mode 100644 java/images/fedora-java8/s2i/assemble create mode 100644 java/images/fedora-java8/s2i/run create mode 100644 java/images/fedora-java8/s2i/s2i-setup create mode 100644 java/images/fedora-java8/s2i/save-artifacts create mode 100644 java/images/fedora-java8/s2i/usage create mode 100644 java/images/fedora-java8/settings.xml diff --git a/java/images.yml b/java/images.yml index 73219183..07bdd2cb 100644 --- a/java/images.yml +++ b/java/images.yml @@ -7,6 +7,17 @@ fish-pepper: config: base: + fedora-java8: + withGradle: true + from: "fedora:29" + user: "jboss" + home: "/opt/jboss" + description: "Fedora S2I Java builder image with OpenJDK 8" + version: + java: "" # empty means latest, currently that's "1:1.8.0.191.b12-8.fc29" + maven: "3.5.4" + jolokia: "1.6.0" + jmxexporter: "0.3.1" centos: withGradle: true from: "centos:7.5.1804" @@ -14,7 +25,7 @@ config: home: "/opt/jboss" description: "CentOS S2I Java builder image with OpenJDK 8" version: - java: "1.8.0.181-3.b13.el7_5" + java: "-1.8.0.181-3.b13.el7_5" maven: "3.5.4" jolokia: "1.6.0" jmxexporter: "0.3.1" diff --git a/java/images/centos/Dockerfile b/java/images/centos/Dockerfile index 5e338dc9..6b8cb9b1 100644 --- a/java/images/centos/Dockerfile +++ b/java/images/centos/Dockerfile @@ -26,7 +26,7 @@ USER root -# Dowload Maven from Apache +# Install Java package & download Maven from Apache RUN yum install -y \ java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5 \ java-1.8.0-openjdk-devel-1.8.0.181-3.b13.el7_5 \ diff --git a/java/images/fedora-java8/Dockerfile b/java/images/fedora-java8/Dockerfile new file mode 100644 index 00000000..aa70de5c --- /dev/null +++ b/java/images/fedora-java8/Dockerfile @@ -0,0 +1,122 @@ +FROM fedora:29 + +ENV JOLOKIA_VERSION="1.6.0" \ + PROMETHEUS_JMX_EXPORTER_VERSION="0.3.1" \ + PATH=$PATH:"/usr/local/s2i" \ + AB_JOLOKIA_PASSWORD_RANDOM="true" \ + AB_JOLOKIA_AUTH_OPENSHIFT="true" \ + JAVA_DATA_DIR="/deployments/data" + +# Some version information +LABEL io.fabric8.s2i.version.maven="3.5.4" \ + io.fabric8.s2i.version.jolokia="1.6.0" \ + io.fabric8.s2i.version.prometheus.jmx_exporter="0.3.1" \ + io.k8s.description="Platform for building and running plain Java applications (fat-jar and flat classpath)" \ + io.k8s.display-name="Java Applications" \ + io.openshift.tags="builder,java" \ + io.openshift.s2i.scripts-url="image:///usr/local/s2i" \ + io.openshift.s2i.destination="/tmp" \ + org.jboss.deployments-dir="/deployments" \ + com.redhat.deployments-dir="/deployments" \ + com.redhat.dev-mode="JAVA_DEBUG:false" \ + com.redhat.dev-mode.port="JAVA_DEBUG_PORT:5005" + +# Temporary switch to root +USER root + + + +# Install Java package & download Maven from Apache +RUN yum install -y \ + java-1.8.0-openjdk \ + java-1.8.0-openjdk-devel \ + && curl https://archive.apache.org/dist/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz | \ + tar -xzf - -C /opt \ + && ln -s /opt/apache-maven-3.5.4 /opt/maven \ + && ln -s /opt/maven/bin/mvn /usr/bin/mvn \ + && groupadd -r jboss -g 1000 \ + && useradd -u 1000 -r -g jboss -m -d /opt/jboss -s /sbin/nologin -c "JBoss user" jboss \ + && chmod 755 /opt/jboss + +ENV JAVA_HOME /etc/alternatives/jre + + +# Use /dev/urandom to speed up startups & Add jboss user to the root group +RUN echo securerandom.source=file:/dev/urandom >> /usr/lib/jvm/java/jre/lib/security/java.security \ + && usermod -g root -G jboss jboss + +# Prometheus JMX exporter agent + RUN mkdir -p /opt/prometheus/etc \ + && curl http://central.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.3.1/jmx_prometheus_javaagent-0.3.1.jar \ + -o /opt/prometheus/jmx_prometheus_javaagent.jar + ADD prometheus-opts /opt/prometheus/prometheus-opts + ADD prometheus-config.yml /opt/prometheus/prometheus-config.yml + RUN chmod 444 /opt/prometheus/jmx_prometheus_javaagent.jar \ + && chmod 444 /opt/prometheus/prometheus-config.yml \ + && chmod 755 /opt/prometheus/prometheus-opts \ + && chmod 775 /opt/prometheus/etc \ + && chgrp root /opt/prometheus/etc + +EXPOSE 9779 + + +# Jolokia agent +RUN mkdir -p /opt/jolokia/etc \ + && curl http://central.maven.org/maven2/org/jolokia/jolokia-jvm/1.6.0/jolokia-jvm-1.6.0-agent.jar \ + -o /opt/jolokia/jolokia.jar +ADD jolokia-opts /opt/jolokia/jolokia-opts +RUN chmod 444 /opt/jolokia/jolokia.jar \ + && chmod 755 /opt/jolokia/jolokia-opts \ + && chmod 775 /opt/jolokia/etc \ + && chgrp root /opt/jolokia/etc + +EXPOSE 8778 + + +# Install rsync +RUN yum install -y rsync + + +# S2I scripts + README +COPY s2i /usr/local/s2i +RUN chmod 755 /usr/local/s2i/* +ADD README.md /usr/local/s2i/usage.txt + +# Add run script as /opt/run-java/run-java.sh and make it executable +COPY run-java.sh /opt/run-java/ +RUN chmod 755 /opt/run-java/run-java.sh + +# Adding run-env.sh to set app dir +COPY run-env.sh /opt/run-java/run-env.sh +RUN chmod 755 /opt/run-java/run-env.sh + + +# Copy licenses +RUN mkdir -p /opt/fuse/licenses +COPY licenses.css /opt/fuse/licenses +COPY licenses.xml /opt/fuse/licenses +COPY licenses.html /opt/fuse/licenses +COPY apache_software_license_version_2.0-apache-2.0.txt /opt/fuse/licenses + + +# Necessary to permit running with a randomised UID +RUN mkdir -p /deployments/data \ + && chmod -R "g+rwX" /deployments \ + && chown -R jboss:root /deployments \ + && chmod -R "g+rwX" /opt/jboss \ + && chown -R jboss:root /opt/jboss \ + && chmod 664 /etc/passwd + +# S2I scripts rely on /opt/jboss as working directory +WORKDIR /opt/jboss + +# S2I requires a numeric, non-0 UID. This is the UID for the jboss user in the base image + +USER 1000 +RUN mkdir -p /opt/jboss/.m2 +COPY settings.xml /opt/jboss/.m2/settings.xml + + +# Use the run script as default since we are working as an hybrid image which can be +# used directly to. (If we were a plain s2i image we would print the usage info here) +CMD [ "/usr/local/s2i/run" ] diff --git a/java/images/fedora-java8/README.md b/java/images/fedora-java8/README.md new file mode 100644 index 00000000..326ebcba --- /dev/null +++ b/java/images/fedora-java8/README.md @@ -0,0 +1,189 @@ +# Fedora S2I Java builder image with OpenJDK 8 + +This is a S2I builder image for Java builds whose result can be run directly without any further application server.It's suited ideally for microservices with a flat classpath (including "far jars"). + +This image also provides an easy integration with an [Jolokia](https://github.com/rhuss/jolokia) agent. See below how to configure this. + +The following environment variables can be used to influence the behaviour of this builder image: + +## Build Time + +* **MAVEN_ARGS** Arguments to use when calling Maven, replacing the default `package hawt-app:build -DskipTests -e`. Please be sure to run the `hawt-app:build` goal (when not already bound to the `package` execution phase), otherwise the startup scripts won't work. +* **MAVEN_ARGS_APPEND** Additional Maven arguments, useful for temporary adding arguments like `-X` or `-am -pl ..` +* **ARTIFACT_DIR** Path to `target/` where the jar files are created for multi module builds. These are added to `${MAVEN_ARGS}` +* **ARTIFACT_COPY_ARGS** Arguments to use when copying artifacts from the output dir to the application dir. Useful to specify which artifacts will be part of the image. It defaults to `-r hawt-app/*` when a `hawt-app` dir is found on the build directory, otherwise jar files only will be included (`*.jar`). +* **MAVEN_CLEAR_REPO** If set then the Maven repository is removed after the artifact is built. This is useful for keeping + the created application image small, but prevents *incremental* builds. The default is `false` + +## Run Time + + +### run-java.sh + +This general purpose startup script is optimized for running Java application from within containers. It is called like + +``` +./run-java.sh +``` +`run-java.sh` knows two sub-commands: + +* `options` to print out JVM option which can be used for own invocation of Java apps (like Maven or Tomcat). It respects container constraints and includes all magic which is used by this script +* `run` executes a Java application as described below. This is also the default command so you can skip adding this command. + +### Running a Java application + +When no subcommand is given (or when you provide the default subcommand `run`), then by default this scripts starts up Java application. + +The startup process is configured mostly via environment variables: + +* **JAVA_APP_DIR** the directory where the application resides. All paths in your application are relative to this directory. By default it is the same directory where this startup script resides. +* **JAVA_LIB_DIR** 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**. +* **JAVA_OPTIONS** options to add when calling `java` +* **JAVA_MAJOR_VERSION** can be 7,8 or 9. If the version is set then only options suitable for this version are used. Actually only 7 is required to set to remove some options known only to Java > 8 +* **JAVA_MAX_MEM_RATIO** is used when no `-Xmx` option is given in `JAVA_OPTIONS`. This is used to calculate a default maximal Heap Memory based on a containers restriction. If used in a Docker container without any memory constraints for the container then this option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio of the container available memory as set here. The default is `25` when the maximum amount of memory available to the container is below 300M, `50` otherwise, which means in that case that 50% of the available memory is used as an upper boundary. You can skip this mechanism by setting this value to 0 in which case no `-Xmx` option is added. +* **JAVA_INIT_MEM_RATIO** is used when no `-Xms` option is given in `JAVA_OPTIONS`. This is used to calculate a default initial Heap Memory based on a containers restriction. If used in a Docker container without any memory constraints for the container then this option has no effect. If there is a memory constraint then `-Xms` is set to a ratio of the container available memory as set here. By default this value is not set. +* **JAVA_MAX_CORE** restrict manually the number of cores available which is used for calculating certain defaults like the number of garbage collector threads. If set to 0 no base JVM tuning based on the number of cores is performed. +* **JAVA_DIAGNOSTICS** set this to get some diagnostics information to standard out when things are happening +* **JAVA_MAIN_CLASS** 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`. +* **JAVA_APP_JAR** A jar file with an appropriate manifest so that it can be started with `java -jar` if no `$JAVA_MAIN_CLASS` is set. In all cases this jar file is added to the classpath, too. +* **JAVA_APP_NAME** Name to use for the process +* **JAVA_CLASSPATH** the classpath to use. If not given, the startup script checks for a file `${JAVA_APP_DIR}/classpath` and use its content literally as classpath. If this file doesn't exists all jars in the app dir are added (`classes:${JAVA_APP_DIR}/*`). +* **JAVA_DEBUG** If set remote debugging will be switched on +* **JAVA_DEBUG_SUSPEND** If set enables suspend mode in remote debugging +* **JAVA_DEBUG_PORT** Port used for remote debugging. Default: 5005 +* **HTTP_PROXY** The URL of the proxy server that translates into the `http.proxyHost` and `http.proxyPort` system properties. +* **HTTPS_PROXY** The URL of the proxy server that translates into the `https.proxyHost` and `https.proxyPort` system properties. +* **no_proxy**, **NO_PROXY** The list of hosts that should be reached directly, bypassing the proxy, that translates into the `http.nonProxyHosts` system property. + +If neither `$JAVA_APP_JAR` nor `$JAVA_MAIN_CLASS` is given, `$JAVA_APP_DIR` is checked for a single JAR file which is taken as `$JAVA_APP_JAR`. If no or more then one jar file is found, an error is thrown. + +The classpath is build up with the following parts: + +* If `$JAVA_CLASSPATH` is set, this classpath is taken. +* The current directory (".") is added first. +* If the current directory is not the same as `$JAVA_APP_DIR`, `$JAVA_APP_DIR` is added. +* If `$JAVA_MAIN_CLASS` is set, then + - A `$JAVA_APP_JAR` is added if set + - If a file `$JAVA_APP_DIR/classpath` exists, its content is appended to the classpath. This file + can be either a single line with the jar files colon separated or a multi-line file where each line + holds the path of the jar file relative to `$JAVA_LIB_DIR` (which by default is the `$JAVA_APP_DIR`) + - If this file is not set, a `${JAVA_APP_DIR}/*` is added which effectively adds all + jars in this directory in alphabetical order. + +These variables can be also set in a shell config file `run-env.sh`, which will be sourced by the startup script. This file can be located in the directory where the startup script is located and in `${JAVA_APP_DIR}`, whereas environment variables in the latter override the ones in `run-env.sh` from the script directory. + +This startup script also checks for a command `run-java-options`. If existent it will be called and the output is added to the environment variable `$JAVA_OPTIONS`. + +The startup script also exposes some environment variables describing container limits which can be used by applications: + +* **CONTAINER_CORE_LIMIT** a calculated core limit as described in https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt +* **CONTAINER_MAX_MEMORY** memory limit given to the container + +Any arguments given to the script are given through directly as argument to the Java application. + +Example: + +``` +# Set the application directory directly +export JAVA_APP_DIR=/deployments +# Set -Xmx based on container constraints +export JAVA_MAX_MEM_RATIO=40 +# Start the jar in JAVA_APP_DIR with the given arguments +./run-java.sh --user maxmorlock --password secret +``` + +### Options + +This script can also be used to calculate reasonable, best-practice options for starting Java apps in general. For example, when running Maven in a container it makes sense to respect container Memory constraints. + +The subcommand `options` can be used to print options to standard output so that is can be easily used to feed it to another, Java based application. + +When no extra arguments are given, all defaults will be used, which can be influenced with the environment variables described above. + +You can select specific sets of options by providing additional arguments: + +* `--debug` : Java debug options if `JAVA_DEBUG` is set +* `--memory` : Memory settings based on the environment variables given +* `--proxy` : Evaluate proxy environments variables +* `--cpu` : Tuning when the number of cores is limited +* `--gc` : GC tuning parameters +* `--jit` : JIT options +* `--diagnostics` : Print diagnostics options when `JAVA_DIAGNOSTICS` is set +* `--java-default` : Same as `--memory --jit --diagnostic --cpu --gc` + +Example: + +``` +# Call Maven with the proper memory settings when running in an container +export MAVEN_OPTS="$(run-java.sh options --memory)" +mvn clean install +``` + + +#### Jolokia configuration + +* **AB_JOLOKIA_OFF** : If set disables activation of Jolokia (i.e. echos an empty value). By default, Jolokia is enabled. +* **AB_JOLOKIA_CONFIG** : If set uses this file (including path) as Jolokia JVM agent properties (as described + in Jolokia's [reference manual](http://www.jolokia.org/reference/html/agents.html#agents-jvm)). If not set, + the `/opt/jolokia/etc/jolokia.properties` will be created using the settings as defined in this document, otherwise + the reset of the settings in this document are ignored. +* **AB_JOLOKIA_HOST** : Host address to bind to (Default: `0.0.0.0`) +* **AB_JOLOKIA_PORT** : Port to use (Default: `8778`) +* **AB_JOLOKIA_USER** : User for basic authentication. Defaults to 'jolokia' +* **AB_JOLOKIA_PASSWORD** : Password for basic authentication. By default authentication is switched off. +* **AB_JOLOKIA_PASSWORD_RANDOM** : Should a random AB_JOLOKIA_PASSWORD be generated? Generated value will be written to `/opt/jolokia/etc/jolokia.pw` +* **AB_JOLOKIA_HTTPS** : Switch on secure communication with https. By default self signed server certificates are generated + if no `serverCert` configuration is given in `AB_JOLOKIA_OPTS` +* **AB_JOLOKIA_ID** : Agent ID to use (`$HOSTNAME` by default, which is the container id) +* **AB_JOLOKIA_DISCOVERY_ENABLED** : Enable Jolokia discovery. Defaults to false. +* **AB_JOLOKIA_OPTS** : Additional options to be appended to the agent configuration. They should be given in the format + "key=value,key=value,..." + +Some options for integration in various environments: + +* **AB_JOLOKIA_AUTH_OPENSHIFT** : Switch on client authentication for OpenShift TSL communication. The value of this + parameter can be a relative distinguished name which must be contained in a presented client certificate. Enabling this + parameter will automatically switch Jolokia into https communication mode. The default CA cert is set to + `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt` + + + +Application arguments can be provided by setting the variable **JAVA_ARGS** to the corresponding value. + +## Spring Boot Automatic Restarts + +This image also supports detecting jars with [Spring Boot devtools](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-devtools) included, which allows automatic restarts when files on the classpath are updated. Files can be easily updated in OpenShift using command [`oc rsync`](https://docs.openshift.org/latest/dev_guide/copy_files_to_container.html). + +To enable automatic restarts, three things are required: + +1. Add Spring Boot devtools dependency: + +```xml + + + org.springframework.boot + spring-boot-devtools + true + + +``` + +2. Add dependency to the generated fat jar by setting `excludeDevtools` configuration property to false: + +```xml + + + + org.springframework.boot + spring-boot-maven-plugin + + false + + + + +``` + +3. Set environment variables `JAVA_DEBUG=true` or `DEBUG=true` and optionally `JAVA_DEBUG_PORT=` or `DEBUG_PORT=`, which defaults to 5005. Since the `DEBUG` variable clashes with Spring Boot's recognition of the same variable to enable Spring Boot debug logging, use `SPRINGBOOT_DEBUG` instead. + +WARNING: Do not use devtools in production!!! This can be accomplished in Maven using a custom profile. diff --git a/java/images/fedora-java8/apache_software_license_version_2.0-apache-2.0.txt b/java/images/fedora-java8/apache_software_license_version_2.0-apache-2.0.txt new file mode 100644 index 00000000..b09cd785 --- /dev/null +++ b/java/images/fedora-java8/apache_software_license_version_2.0-apache-2.0.txt @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/java/images/fedora-java8/jolokia-opts b/java/images/fedora-java8/jolokia-opts new file mode 100644 index 00000000..defd7955 --- /dev/null +++ b/java/images/fedora-java8/jolokia-opts @@ -0,0 +1,94 @@ +#!/bin/sh + +# Check whether a given config is contained in AB_JOLOKIA_OPTS +is_in_jolokia_opts() { + local prop=$1 + if [ -n "${AB_JOLOKIA_OPTS:-}" ] && [ "${AB_JOLOKIA_OPTS}" != "${AB_JOLOKIA_OPTS/${prop}/}" ]; then + echo "yes" + else + echo "no" + fi +} + +get_jolokia_properties() { + + echo "host=${AB_JOLOKIA_HOST:-*}" + echo "port=${AB_JOLOKIA_PORT:-8778}" + echo "discoveryEnabled=${AB_JOLOKIA_DISCOVERY_ENABLED:-false}" + + if [ -n "${AB_JOLOKIA_PASSWORD:-}" ]; then + echo "user=${AB_JOLOKIA_USER:-jolokia}" + echo "password=${AB_JOLOKIA_PASSWORD}" + fi + if [ -n "${AB_JOLOKIA_HTTPS:-}" ]; then + echo "protocol=https" + https_used=1 + fi + + # Integration with OpenShift client cert auth is enabled + # by default if not explicitly turned off by setting to 'false' + if [ "${AB_JOLOKIA_AUTH_OPENSHIFT:-}" != "false" ] && [ -f "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" ]; then + echo "useSslClientAuthentication=true" + echo "extraClientCheck=true" + + # Check if the 'protocol' property has already been set to 'https' + # If not, then defaults to using HTTPS + if [ -z ${https_used+x} ]; then + echo "protocol=https" + fi + if [ $(is_in_jolokia_opts "caCert") != "yes" ]; then + echo "caCert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" + fi + + if [ $(is_in_jolokia_opts "clientPrincipal") != "yes" ]; then + if [ "${AB_JOLOKIA_AUTH_OPENSHIFT}" != "${AB_JOLOKIA_AUTH_OPENSHIFT/=/}" ]; then + # Supposed to contain a principal name to check + echo "clientPrincipal=$(echo ${AB_JOLOKIA_AUTH_OPENSHIFT} | sed -e 's/ /\\\\ /g')" + else + echo "clientPrincipal=cn=system:master-proxy" + fi + fi + fi + + # Add extra opts + if [ -n "${AB_JOLOKIA_OPTS:-}" ]; then + echo "${AB_JOLOKIA_OPTS}" | tr "," "\n" + fi + +} + +write_jolokia_properties() { + local jolokia_property_file="$1" + + # Setup Jolokia to accept basic auth, using a randomly generated password that is stored + # in the container in the ${DEPLOYMENTS_DIR}/jolokia.pw file. + if [ "${AB_JOLOKIA_PASSWORD_RANDOM:-}" == "true" ]; then + pw_file="/opt/jolokia/etc/jolokia.pw" + if [ -f "${pw_file}" ] ; then + AB_JOLOKIA_PASSWORD=$(cat "${pw_file}") + else + AB_JOLOKIA_PASSWORD=$(tr -cd '[:alnum:]' < /dev/urandom | fold -w30 | head -n1) + touch "${pw_file}" + chmod 660 "${pw_file}" + cat > "${pw_file}" < "${jolokia_property_file}" < + + + + JBoss Fuse + + +

JBoss Fuse

+

The following material has been provided for informational purposes only, and should + not be relied upon or construed as a legal opinion or legal advice. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Package GroupPackage ArtifactPackage VersionRemote LicensesLocal Licenses
org.apache.mavenmaven3.5.4Apache Software License, Version 2.0
apache software license, version 2.0 - apache-2.0.txt
org.jolokiajolokia1.6.0Apache Software License, Version 2.0
apache software license, version 2.0 - apache-2.0.txt
io.prometheus.jmxjmx_prometheus_javaagent0.3.1Apache Software License, Version 2.0
apache software license, version 2.0 - apache-2.0.txt
+ + diff --git a/java/images/fedora-java8/licenses.xml b/java/images/fedora-java8/licenses.xml new file mode 100644 index 00000000..b4f2db7d --- /dev/null +++ b/java/images/fedora-java8/licenses.xml @@ -0,0 +1,41 @@ + + + + + org.apache.maven + maven + 3.5.4 + + + Apache Software License, Version 2.0 + http://repository.jboss.org/licenses/apache-2.0.txt + repo + + + + + org.jolokia + jolokia + 1.6.0 + + + Apache Software License, Version 2.0 + http://repository.jboss.org/licenses/apache-2.0.txt + repo + + + + + io.prometheus.jmx + jmx_prometheus_javaagent + 0.3.1 + + + Apache Software License, Version 2.0 + http://repository.jboss.org/licenses/apache-2.0.txt + repo + + + + + diff --git a/java/images/fedora-java8/prometheus-config.yml b/java/images/fedora-java8/prometheus-config.yml new file mode 100644 index 00000000..700713e5 --- /dev/null +++ b/java/images/fedora-java8/prometheus-config.yml @@ -0,0 +1,586 @@ +startDelaySecs: 5 +ssl: false +blacklistObjectNames: ["java.lang:*"] +rules: +# Context level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + type: context + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + type: context + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + type: context + type: GAUGE + + +# Route level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + route: $2 + type: routes + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + route: $2 + type: routes + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + +# Processor level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + +# Consumers + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + consumer: $2 + type: consumers + type: GAUGE + +# Services + - pattern: 'org.apache.camel<>MaxDuration' + name: org.apache.camel.MaxDuration + help: Maximum Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>MeanDuration' + name: org.apache.camel.MeanDuration + help: Mean Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>MinDuration' + name: org.apache.camel.MinDuration + help: Minimum Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>TotalDuration' + name: org.apache.camel.TotalDuration + help: Total Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>ThreadsBlocked' + name: org.apache.camel.ThreadsBlocked + help: Threads Blocked + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>ThreadsInterrupted' + name: org.apache.camel.ThreadsInterrupted + help: Threads Interrupted + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.cxf<>NumLogicalRuntimeFaults' + name: org.apache.cxf.NumLogicalRuntimeFaults + help: Number of logical runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumLogicalRuntimeFaults' + name: org.apache.cxf.NumLogicalRuntimeFaults + help: Number of logical runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>AvgResponseTime' + name: org.apache.cxf.AvgResponseTime + help: Average Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>AvgResponseTime' + name: org.apache.cxf.AvgResponseTime + help: Average Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumInvocations' + name: org.apache.cxf.NumInvocations + help: Number of invocations + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumInvocations' + name: org.apache.cxf.NumInvocations + help: Number of invocations + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>MaxResponseTime' + name: org.apache.cxf.MaxResponseTime + help: Maximum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>MaxResponseTime' + name: org.apache.cxf.MaxResponseTime + help: Maximum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>MinResponseTime' + name: org.apache.cxf.MinResponseTime + help: Minimum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>MinResponseTime' + name: org.apache.cxf.MinResponseTime + help: Minimum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>TotalHandlingTime' + name: org.apache.cxf.TotalHandlingTime + help: Total Handling Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>TotalHandlingTime' + name: org.apache.cxf.TotalHandlingTime + help: Total Handling Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumRuntimeFaults' + name: org.apache.cxf.NumRuntimeFaults + help: Number of runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumRuntimeFaults' + name: org.apache.cxf.NumRuntimeFaults + help: Number of runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumUnCheckedApplicationFaults' + name: org.apache.cxf.NumUnCheckedApplicationFaults + help: Number of unchecked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumUnCheckedApplicationFaults' + name: org.apache.cxf.NumUnCheckedApplicationFaults + help: Number of unchecked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumCheckedApplicationFaults' + name: org.apache.cxf.NumCheckedApplicationFaults + help: Number of checked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumCheckedApplicationFaults' + name: org.apache.cxf.NumCheckedApplicationFaults + help: Number of checked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 diff --git a/java/images/fedora-java8/prometheus-opts b/java/images/fedora-java8/prometheus-opts new file mode 100644 index 00000000..931f9528 --- /dev/null +++ b/java/images/fedora-java8/prometheus-opts @@ -0,0 +1,57 @@ +#!/bin/sh + +# Check whether a given config is contained in AB_PROMETHEUS_OPTS +is_in_prometheus_opts() { + local prop=$1 + if [ -n "${AB_JMX_EXPORTER_OPTS:-}" ] && [ "${AB_JMX_EXPORTER_OPTS}" != "${AB_JMX_EXPORTER_OPTS/${prop}/}" ]; then + echo "yes" + else + echo "no" + fi +} + +get_prometheus_properties() { + + echo "port=${AB_JMX_EXPORTER_PORT:-9779}" + echo "config=${AB_JMX_EXPORTER_CONFIG:-/opt/prometheus/prometheus-config.yml}" + + if [ -n "${AB_PROMETHEUS_OPTS:-}" ]; then + echo "${AB_PROMETHEUS_OPTS}" | tr "," "\n" + fi + +} + +write_prometheus_properties() { + local prometheus_property_file="$1" + + touch "${prometheus_property_file}" + chmod 660 "${prometheus_property_file}" + cat > "${prometheus_property_file}" < +# +# # Get options which can be used for invoking Java apps like Maven or Tomcat +# ./run-java.sh options [....] +# +# +# This script will pick up either a 'fat' jar which can be run with "-jar" +# or you can sepcify a JAVA_MAIN_CLASS. +# +# Source and Documentation can be found +# at https://github.com/fabric8io-images/run-java-sh +# +# Env-variables evaluated in this script: +# +# JAVA_OPTIONS: Checked for already set options +# JAVA_MAX_MEM_RATIO: Ratio use to calculate a default maximum Memory, in percent. +# E.g. the "50" value implies that 50% of the Memory +# given to the container is used as the maximum heap memory with +# '-Xmx'. +# It defaults to "25" when the maximum amount of memory available +# to the container is below 300M, otherwise defaults to "50". +# It is a heuristic and should be better backed up with real +# experiments and measurements. +# For a good overviews what tuning options are available --> +# https://youtu.be/Vt4G-pHXfs4 +# https://www.youtube.com/watch?v=w1rZOY5gbvk +# https://vimeo.com/album/4133413/video/181900266 +# Also note that heap is only a small portion of the memory used by a JVM. There are lot +# of other memory areas (metadata, thread, code cache, ...) which addes to the overall +# size. When your container gets killed because of an OOM, then you should tune +# the absolute values. +# JAVA_INIT_MEM_RATIO: Ratio use to calculate a default intial heap memory, in percent. +# By default this value is not set. +# +# The following variables are exposed to your Java application: +# +# CONTAINER_MAX_MEMORY: Max memory for the container (if running within a container) +# MAX_CORE_LIMIT: Number of cores available for the container (if running within a container) + + +# ========================================================== + +# Fail on a single failed command in a pipeline (if supported) +(set -o | grep -q pipefail) && set -o pipefail + +# Fail on error and undefined vars +set -eu + +# Save global script args +ARGS="$@" + +# ksh is different for defining local vars +if [ -n "${KSH_VERSION:-}" ]; then + alias local=typeset +fi + +# Error is indicated with a prefix in the return value +check_error() { + local error_msg="$1" + if echo "${error_msg}" | grep -q "^ERROR:"; then + echo "${error_msg}" + exit 1 + fi +} + +# The full qualified directory where this script is located in +script_dir() { + # Default is current directory + local dir=$(dirname "$0") + local full_dir=$(cd "${dir}" && pwd) + echo ${full_dir} +} + +# 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 + local nr_jars="$(ls 2>/dev/null | grep -e '.*\.jar$' | grep -v '^original-' | wc -l | awk '{print $1}')" + if [ "${nr_jars}" = 1 ]; then + ls *.jar | grep -v '^original-' + exit 0 + fi + cd "${old_dir}" + echo "ERROR: Neither JAVA_MAIN_CLASS nor JAVA_APP_JAR is set and ${nr_jars} found in ${dir} (1 expected)" + else + echo "ERROR: No directory ${dir} found for auto detection" + fi +} + +# Check directories (arg 2...n) for a jar file (arg 1) +find_jar_file() { + local jar="$1" + shift; + + # Absolute path check if jar specifies an absolute path + if [ "${jar}" != ${jar#/} ]; then + if [ -f "${jar}" ]; then + echo "${jar}" + else + echo "ERROR: No such file ${jar}" + fi + else + for dir in $*; do + if [ -f "${dir}/$jar" ]; then + echo "${dir}/$jar" + return + fi + done + echo "ERROR: No ${jar} found in $*" + fi +} + +# Generic formula evaluation based on awk +calc() { + local formula="$1" + shift + echo "$@" | awk ' + function ceil(x) { + return x % 1 ? int(x) + 1 : x + } + function log2(x) { + return log(x)/log(2) + } + function max2(x, y) { + return x > y ? x : y + } + function round(x) { + return int(x + 0.5) + } + {print '"int(${formula})"'} + ' +} + +# Based on the cgroup limits, figure out the max number of core we should utilize +core_limit() { + local cpu_period_file="/sys/fs/cgroup/cpu/cpu.cfs_period_us" + local cpu_quota_file="/sys/fs/cgroup/cpu/cpu.cfs_quota_us" + if [ -r "${cpu_period_file}" ]; then + local cpu_period="$(cat ${cpu_period_file})" + + if [ -r "${cpu_quota_file}" ]; then + local cpu_quota="$(cat ${cpu_quota_file})" + # cfs_quota_us == -1 --> no restrictions + if [ ${cpu_quota:-0} -ne -1 ]; then + echo $(calc 'ceil($1/$2)' "${cpu_quota}" "${cpu_period}") + fi + fi + fi +} + +max_memory() { + # High number which is the max limit until which memory is supposed to be + # unbounded. + local mem_file="/sys/fs/cgroup/memory/memory.limit_in_bytes" + if [ -r "${mem_file}" ]; then + local max_mem_cgroup="$(cat ${mem_file})" + local max_mem_meminfo_kb="$(cat /proc/meminfo | awk '/MemTotal/ {print $2}')" + local max_mem_meminfo="$(expr $max_mem_meminfo_kb \* 1024)" + if [ ${max_mem_cgroup:-0} != -1 ] && [ ${max_mem_cgroup:-0} -lt ${max_mem_meminfo:-0} ] + then + echo "${max_mem_cgroup}" + fi + fi +} + +init_limit_env_vars() { + # Read in container limits and export the as environment variables + local core_limit="$(core_limit)" + if [ -n "${core_limit}" ]; then + export CONTAINER_CORE_LIMIT="${core_limit}" + fi + + local mem_limit="$(max_memory)" + if [ -n "${mem_limit}" ]; then + export CONTAINER_MAX_MEMORY="${mem_limit}" + fi +} + +load_env() { + local script_dir="$1" + + # Configuration stuff is read from this file + local run_env_sh="run-env.sh" + + # Load default default config + if [ -f "${script_dir}/${run_env_sh}" ]; then + . "${script_dir}/${run_env_sh}" + fi + + # Check also $JAVA_APP_DIR. Overrides other defaults + # It's valid to set the app dir in the default script + JAVA_APP_DIR="${JAVA_APP_DIR:-${script_dir}}" + if [ -f "${JAVA_APP_DIR}/${run_env_sh}" ]; then + . "${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 [ -n "${JAVA_APP_JAR:-}" ]; then + local jar="$(find_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 +} + +# Check for standard /opt/run-java-options first, fallback to run-java-options in the path if not existing +run_java_options() { + if [ -f "/opt/run-java-options" ]; then + echo "$(. /opt/run-java-options)" + else + which run-java-options >/dev/null 2>&1 + if [ $? = 0 ]; then + echo "$(run-java-options)" + fi + fi +} + +debug_options() { + if [ -n "${JAVA_ENABLE_DEBUG:-}" ] || [ -n "${JAVA_DEBUG_ENABLE:-}" ] || [ -n "${JAVA_DEBUG:-}" ]; then + local debug_port="${JAVA_DEBUG_PORT:-5005}" + local suspend_mode="n" + if [ -n "${JAVA_DEBUG_SUSPEND:-}" ]; then + if ! echo "${JAVA_DEBUG_SUSPEND}" | grep -q -e '^\(false\|n\|no\|0\)$'; then + suspend_mode="y" + fi + fi + echo "-agentlib:jdwp=transport=dt_socket,server=y,suspend=${suspend_mode},address=${debug_port}" + fi +} + +# Read in a classpath either from a file with a single line, colon separated +# or given line-by-line in separate lines +# Arg 1: path to claspath (must exist), optional arg2: application jar, which is stripped from the classpath in +# multi line arrangements +format_classpath() { + local cp_file="$1" + local app_jar="${2:-}" + + local wc_out="$(wc -l $1 2>&1)" + if [ $? -ne 0 ]; then + echo "Cannot read lines in ${cp_file}: $wc_out" + exit 1 + fi + + local nr_lines=$(echo $wc_out | awk '{ print $1 }') + if [ ${nr_lines} -gt 1 ]; then + local sep="" + local classpath="" + while read file; do + local full_path="${JAVA_LIB_DIR}/${file}" + # Don't include app jar if include in list + if [ "${app_jar}" != "${full_path}" ]; then + classpath="${classpath}${sep}${full_path}" + fi + sep=":" + done < "${cp_file}" + echo "${classpath}" + else + # Supposed to be a single line, colon separated classpath file + cat "${cp_file}" + fi +} + +# ========================================================================== + +memory_options() { + echo "$(calc_init_memory) $(calc_max_memory)" + return +} + +# Check for memory options and set max heap size if needed +calc_max_memory() { + # Check whether -Xmx is already given in JAVA_OPTIONS + if echo "${JAVA_OPTIONS:-}" | grep -q -- "-Xmx"; then + return + fi + + if [ -z "${CONTAINER_MAX_MEMORY:-}" ]; then + return + fi + + # Check for the 'real memory size' and calculate Xmx from the ratio + if [ -n "${JAVA_MAX_MEM_RATIO:-}" ]; then + if [ "${JAVA_MAX_MEM_RATIO}" -eq 0 ]; then + # Explicitely switched off + return + fi + calc_mem_opt "${CONTAINER_MAX_MEMORY}" "${JAVA_MAX_MEM_RATIO}" "mx" + elif [ "${CONTAINER_MAX_MEMORY}" -le 314572800 ]; then + # Restore the one-fourth default heap size instead of the one-half below 300MB threshold + # See https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/parallel.html#default_heap_size + calc_mem_opt "${CONTAINER_MAX_MEMORY}" "25" "mx" + else + calc_mem_opt "${CONTAINER_MAX_MEMORY}" "50" "mx" + fi +} + +# Check for memory options and set initial heap size if requested +calc_init_memory() { + # Check whether -Xms is already given in JAVA_OPTIONS. + if echo "${JAVA_OPTIONS:-}" | grep -q -- "-Xms"; then + return + fi + + # Check if value set + if [ -z "${JAVA_INIT_MEM_RATIO:-}" ] || [ -z "${CONTAINER_MAX_MEMORY:-}" ] || [ "${JAVA_INIT_MEM_RATIO}" -eq 0 ]; then + return + fi + + # Calculate Xms from the ratio given + calc_mem_opt "${CONTAINER_MAX_MEMORY}" "${JAVA_INIT_MEM_RATIO}" "ms" +} + +calc_mem_opt() { + local max_mem="$1" + local fraction="$2" + local mem_opt="$3" + + local val=$(calc 'round($1*$2/100/1048576)' "${max_mem}" "${fraction}") + echo "-X${mem_opt}${val}m" +} + +c2_disabled() { + if [ -n "${CONTAINER_MAX_MEMORY:-}" ]; then + # Disable C2 compiler when container memory <=300MB + if [ "${CONTAINER_MAX_MEMORY}" -le 314572800 ]; then + echo true + return + fi + fi + echo false +} + +jit_options() { + # Check whether -XX:TieredStopAtLevel is already given in JAVA_OPTIONS + if echo "${JAVA_OPTIONS:-}" | grep -q -- "-XX:TieredStopAtLevel"; then + return + fi + if [ $(c2_disabled) = true ]; then + echo "-XX:TieredStopAtLevel=1" + fi +} + +# Switch on diagnostics except when switched off +diagnostics_options() { + if [ -n "${JAVA_DIAGNOSTICS:-}" ]; then + echo "-XX:NativeMemoryTracking=summary -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UnlockDiagnosticVMOptions" + fi +} + +# Replicate thread ergonomics for tiered compilation. +# This could ideally be skipped when tiered compilation is disabled. +# The algorithm is taken from: +# OpenJDK / jdk8u / jdk8u / hotspot +# src/share/vm/runtime/advancedThresholdPolicy.cpp +ci_compiler_count() { + local core_limit="$1" + local log_cpu=$(calc 'log2($1)' "$core_limit") + local loglog_cpu=$(calc 'log2(max2($1,1))' "$log_cpu") + local count=$(calc 'max2($1*$2,1)*3/2' "$log_cpu" "$loglog_cpu") + local c1_count=$(calc 'max2($1/3,1)' "$count") + local c2_count=$(calc 'max2($1-$2,1)' "$count" "$c1_count") + [ $(c2_disabled) = true ] && echo "$c1_count" || echo $(calc '$1+$2' "$c1_count" "$c2_count") +} + +cpu_options() { + local core_limit="${JAVA_CORE_LIMIT:-}" + if [ "$core_limit" = "0" ]; then + return + fi + + if [ -n "${CONTAINER_CORE_LIMIT:-}" ]; then + if [ -z ${core_limit} ]; then + core_limit="${CONTAINER_CORE_LIMIT}" + fi + echo "-XX:ParallelGCThreads=${core_limit} " \ + "-XX:ConcGCThreads=${core_limit} " \ + "-Djava.util.concurrent.ForkJoinPool.common.parallelism=${core_limit} " \ + "-XX:CICompilerCount=$(ci_compiler_count $core_limit)" + fi +} + +#-XX:MinHeapFreeRatio=20 These parameters tell the heap to shrink aggressively and to grow conservatively. +#-XX:MaxHeapFreeRatio=40 Thereby optimizing the amount of memory available to the operating system. +heap_ratio() { + echo "-XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40" +} + +# These parameters are necessary when running parallel GC if you want to use the Min and Max Heap Free ratios. +# Skip setting gc_options if any other GC is set in JAVA_OPTIONS. +# -XX:GCTimeRatio=4 +# -XX:AdaptiveSizePolicyWeight=90 +gc_options() { + if echo "${JAVA_OPTIONS:-}" | grep -q -- "-XX:.*Use.*GC"; then + return + fi + local opts="-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 $(heap_ratio)" + if [ -z "${JAVA_MAJOR_VERSION:-}" ] || [ "${JAVA_MAJOR_VERSION:-}" != "7" ]; then + opts="${opts} -XX:+ExitOnOutOfMemoryError" + fi + echo $opts +} + +java_default_options() { + # Echo options, trimming trailing and multiple spaces + echo "$(memory_options) $(jit_options) $(diagnostics_options) $(cpu_options) $(gc_options)" | awk '$1=$1' + +} + +# ============================================================================== + +# parse the URL +parse_url() { + #[scheme://][user[:password]@]host[:port][/path][?params] + echo "$1" | sed -e "s+^\(\([^:]*\)://\)\?\(\([^:@]*\)\(:\([^@]*\)\)\?@\)\?\([^:/?]*\)\(:\([^/?]*\)\)\?.*$+ local scheme='\2' username='\4' password='\6' hostname='\7' port='\9'+" +} + +java_proxy_options() { + local url="$1" + local transport="$2" + local ret="" + + if [ -n "$url" ] ; then + eval $(parse_url "$url") + if [ -n "$hostname" ] ; then + ret="-D${transport}.proxyHost=${hostname}" + fi + if [ -n "$port" ] ; then + ret="$ret -D${transport}.proxyPort=${port}" + fi + if [ -n "$username" -o -n "$password" ] ; then + echo "WARNING: Proxy URL for ${transport} contains authentication credentials, these are not supported by java" >&2 + fi + fi + echo "$ret" +} + +# Check for proxy options and echo if enabled. +proxy_options() { + local ret="" + ret="$(java_proxy_options "${https_proxy:-${HTTPS_PROXY:-}}" https)" + ret="$ret $(java_proxy_options "${http_proxy:-${HTTP_PROXY:-}}" http)" + + local noProxy="${no_proxy:-${NO_PROXY:-}}" + if [ -n "$noProxy" ] ; then + ret="$ret -Dhttp.nonProxyHosts=\"$(echo "|$noProxy" | sed -e 's/,[[:space:]]*/|/g' | sed -e 's/|\./|\*\./g' | cut -c 2-)\"" + fi + echo "$ret" +} + +# ============================================================================== + +# Set process name if possible +exec_args() { + EXEC_ARGS="" + if [ -n "${JAVA_APP_NAME:-}" ]; then + # Not all shells support the 'exec -a newname' syntax.. + if $(exec -a test true 2>/dev/null); then + echo "-a '${JAVA_APP_NAME}'" + fi + fi +} + +# Combine all java options +java_options() { + # Normalize spaces with awk (i.e. trim and elimate double spaces) + # See e.g. https://www.physicsforums.com/threads/awk-1-1-1-file-txt.658865/ for an explanation + # of this awk idiom + echo "${JAVA_OPTIONS:-} $(run_java_options) $(debug_options) $(proxy_options) $(java_default_options)" | awk '$1=$1' +} + +# Fetch classpath from env or from a local "run-classpath" file +classpath() { + local cp_path="." + if [ "${JAVA_LIB_DIR}" != "${JAVA_APP_DIR}" ]; then + cp_path="${cp_path}:${JAVA_LIB_DIR}" + fi + if [ -z "${JAVA_CLASSPATH:-}" ] && [ -n "${JAVA_MAIN_CLASS:-}" ]; then + if [ -n "${JAVA_APP_JAR:-}" ]; then + cp_path="${cp_path}:${JAVA_APP_JAR}" + fi + if [ -f "${JAVA_LIB_DIR}/classpath" ]; then + # Classpath is pre-created and stored in a 'run-classpath' file + cp_path="${cp_path}:$(format_classpath ${JAVA_LIB_DIR}/classpath ${JAVA_APP_JAR:-})" + else + # No order implied + cp_path="${cp_path}:${JAVA_APP_DIR}/*" + fi + elif [ -n "${JAVA_CLASSPATH:-}" ]; then + # Given from the outside + cp_path="${JAVA_CLASSPATH}" + fi + echo "${cp_path}" +} + +# Checks if a flag is present in the arguments. +hasflag() { + local filters="$@" + for var in $ARGS; do + for filter in $filters; do + if [ "$var" = "$filter" ]; then + echo 'true' + return + fi + done + done +} + +# ============================================================================== + +options() { + if [ -z ${1:-} ]; then + java_options + return + fi + + local ret="" + if [ $(hasflag --debug) ]; then + ret="$ret $(debug_options)" + fi + if [ $(hasflag --proxy) ]; then + ret="$ret $(proxy_options)" + fi + if [ $(hasflag --java-default) ]; then + ret="$ret $(java_default_options)" + fi + if [ $(hasflag --memory) ]; then + ret="$ret $(memory_options)" + fi + if [ $(hasflag --jit) ]; then + ret="$ret $(jit_options)" + fi + if [ $(hasflag --diagnostics) ]; then + ret="$ret $(diagnostics_options)" + fi + if [ $(hasflag --cpu) ]; then + ret="$ret $(cpu_options)" + fi + if [ $(hasflag --gc) ]; then + ret="$ret $(gc_options)" + fi + + echo $ret | awk '$1=$1' +} + +# Start JVM +run() { + # Initialize environment + load_env $(script_dir) + + local args + cd ${JAVA_APP_DIR} + if [ -n "${JAVA_MAIN_CLASS:-}" ] ; then + args="${JAVA_MAIN_CLASS}" + else + # Either JAVA_MAIN_CLASS or JAVA_APP_JAR has been set in load_env() + # So no ${JAVA_APP_JAR:-} safeguard is needed here. Actually its good when the script + # dies here if JAVA_APP_JAR would not be set for some reason (see option `set -u` above) + args="-jar ${JAVA_APP_JAR}" + fi + # Don't put ${args} in quotes, otherwise it would be interpreted as a single arg. + # However it could be two args (see above). zsh doesn't like this btw, but zsh is not + # supported anyway. + echo exec $(exec_args) java $(java_options) -cp "$(classpath)" ${args} $@ + exec $(exec_args) java $(java_options) -cp "$(classpath)" ${args} $@ +} + +# ============================================================================= +# Fire up + +# Set env vars reflecting limits +init_limit_env_vars + +first_arg=${1:-} +if [ "${first_arg}" = "options" ]; then + # Print out options only + shift + options $@ + exit 0 +elif [ "${first_arg}" = "run" ]; then + # Run is the default command, but can be given to allow "options" + # as first argument to your + shift +fi +run $@ diff --git a/java/images/fedora-java8/s2i/assemble b/java/images/fedora-java8/s2i/assemble new file mode 100644 index 00000000..533eb8de --- /dev/null +++ b/java/images/fedora-java8/s2i/assemble @@ -0,0 +1,313 @@ +#!/bin/sh +# Global S2I variable setup +source `dirname "$0"`/s2i-setup + +# Maven arguments setting up the environment +maven_env_args="-Dmaven.repo.local=${S2I_ARTIFACTS_DIR}/m2" + +# ========================================================================= +# Helper functions: + +function check_error() { + local label=$1 + local error=$2 + if [ ${error} -ne 0 ]; then + echo "Aborting due to error code $error for $label" + exit ${error} + fi +} + +function get_maven_output_dir() { + local dir="" + + # If multi module build and no ARTIFACT_DIR is set --> error + if [ x"${ARTIFACT_DIR}" = x ]; then + echo " ${MAVEN_ARGS} ${MAVEN_ARGS_APPEND}" | grep -q ' -pl' + if [ $? -eq 0 ]; then + echo "ARTIFACT_DIR must be set for multi module Maven builds" + exit 1 + fi + dir="${S2I_SOURCE_DIR}/target" + else + if [ "${ARTIFACT_DIR:0:1}" = "/" ]; then + echo "ARTIFACT_DIR \"${ARTIFACT_DIR}\" must not be absolute but relative to the source directory" + exit 1 + fi + dir="${S2I_SOURCE_DIR}/${ARTIFACT_DIR}" + fi + + # Normalize dir + dir=$(echo ${dir} | tr -s /) + dir=${dir%/} + # The parent must exist but target/ won't exist yet + if [ ! -d $(dirname "${dir}"}) ]; then + echo "Please specify an existing build directory ARTIFACT_DIR (tried '$(dirname "${dir}")' which does not exist)" + exit 1 + fi + echo ${dir} +} + +function copy_dir() { + local src=$1 + local dest=$2 + + # Copy recursively and preserve ownership: -a + cp -a ${src}/* ${dest} +} + +function copy_artifacts() { + local dir=$1 + local dest=$2 + + cd ${dir} + + local cp_args=${ARTIFACT_COPY_ARGS} + if [ x"${cp_args}" = x ]; then + if [ -d "hawt-app" ]; then + cp_args="-r hawt-app/*" + else + cp_args="*.jar" + fi + fi + echo "Running: cp -v ${cp_args} ${dest}" + cp -v ${cp_args} ${dest} +} + +function setup_maven() { + if [ -n "$HTTP_PROXY_HOST" -a -n "$HTTP_PROXY_PORT" ]; then + xml="\ + genproxy\ + true\ + http\ + $HTTP_PROXY_HOST\ + $HTTP_PROXY_PORT" + if [ -n "$HTTP_PROXY_USERNAME" -a -n "$HTTP_PROXY_PASSWORD" ]; then + xml="$xml\ + $HTTP_PROXY_USERNAME\ + $HTTP_PROXY_PASSWORD" + fi + if [ -n "$HTTP_PROXY_NONPROXYHOSTS" ]; then + xml="$xml\ + $HTTP_PROXY_NONPROXYHOSTS" + fi + xml="$xml\ + " + sed -i "s||$xml|" $HOME/.m2/settings.xml + fi + + if [ -n "$MAVEN_MIRROR_URL" ]; then + xml=" \ + mirror.default\ + $MAVEN_MIRROR_URL\ + external:*\ + " + sed -i "s||$xml|" $HOME/.m2/settings.xml + fi + + if [ -f "${S2I_SOURCE_DIR}/configuration/settings.xml" ]; then + maven_env_args="${maven_env_args} -s ${S2I_SOURCE_DIR}/configuration/settings.xml" + echo "Using custom maven settings from ${S2I_SOURCE_DIR}/configuration/settings.xml" + fi +} + +function build_maven() { + # Where artifacts are created during build + local build_dir=$1 + + # Where to put the artifacts + local app_dir=$2 + + # Default args: no tests, if a module is specified, only build this module + local maven_args=${MAVEN_ARGS:-package -DskipTests -Dmaven.javadoc.skip=true -Dmaven.site.skip=true -Dmaven.source.skip=true -Djacoco.skip=true -Dcheckstyle.skip=true -Dfindbugs.skip=true -Dpmd.skip=true -Dfabric8.skip=true -e -B} + + # If there is no user provided MAVEN_OPTS, use options from run-java.sh + if [ -f ${RUN_JAVA_DIR}/run-java.sh -a -z "${MAVEN_OPTS}" ]; then + export MAVEN_OPTS=$(${RUN_JAVA_DIR}/run-java.sh options) + fi + + if [ ! -z "${MAVEN_OPTS}" ]; then + echo "Using MAVEN_OPTS '${MAVEN_OPTS}'" + fi + + echo "Found pom.xml ... " + + local old_dir=$(pwd) + cd ${S2I_SOURCE_DIR} + check_error "changing directory to ${S2I_SOURCE_DIR}" $? + + local mvn="mvn" + + + # ========= + # Run Maven + echo "Running 'mvn ${maven_env_args} ${maven_args} ${MAVEN_ARGS_APPEND}'" + ${mvn} ${maven_env_args} --version + ${mvn} ${maven_env_args} ${maven_args} ${MAVEN_ARGS_APPEND} + check_error "Maven build" $? + + # ============== + # Copy artifacts + echo "Copying Maven artifacts from ${build_dir} to ${app_dir} ..." + copy_artifacts ${build_dir} ${app_dir} + check_error "copying artifacts from ${build_dir} to ${app_dir}" $? + + # ====================== + # ====================== + # Remove repo if desired + if [ "x${MAVEN_CLEAR_REPO}" != "x" ]; then + rm -rf "${S2I_ARTIFACTS_DIR}/m2" + check_error "Cannot remove local Maven repository ${S2I_ARTIFACTS_DIR}/m2" $? + fi + + cd ${old_dir} +} + + +# ========================================================================= +# Gradle support + +function get_gradle_output_dir() { + local dir="" + + # If multi module build and no ARTIFACT_DIR is set --> error + if [ x"${ARTIFACT_DIR}" = x ]; then + dir="${S2I_SOURCE_DIR}/build/libs" + else + if [ "${ARTIFACT_DIR:0:1}" = "/" ]; then + echo "ARTIFACT_DIR \"${ARTIFACT_DIR}\" must not be absolute but relative to the source directory" + exit 1 + fi + dir="${S2I_SOURCE_DIR}/${ARTIFACT_DIR}" + fi + + echo ${dir} +} + +function build_gradle() { + # Where artifacts are created during build + local build_dir=$1 + + # Where to put the artifacts + local app_dir=$2 + + # Default args + local gradle_args=${GRADLE_ARGS:-build -x test} + + # If there is no user provided GRADLE_OPTS, use options from run-java.sh + if [ -f "${RUN_JAVA_DIR}/run-java.sh" ] && [ -z "${GRADLE_OPTS}" ]; then + export GRADLE_OPTS=$(${RUN_JAVA_DIR}/run-java.sh options) + fi + + if [ ! -z "${GRADLE_OPTS}" ]; then + echo "Using GRADLE_OPTS '${GRADLE_OPTS}'" + fi + + local old_dir=$(pwd) + cd ${S2I_SOURCE_DIR} + check_error "changing directory to ${S2I_SOURCE_DIR}" $? + + # ========= + # Run Gradle + echo "Running './gradlew --no-daemon ${gradle_args} ${GRADLE_ARGS_APPEND}'" + ./gradlew --no-daemon ${gradle_args} ${GRADLE_ARGS_APPEND} + check_error "Gradle build" $? + + # ============== + # Copy artifacts + echo "Copying Gradle artifacts from ${build_dir} to ${app_dir} ..." + copy_artifacts ${build_dir} ${app_dir} + check_error "copying artifacts from ${build_dir} to ${app_dir}" $? + + # ====================== + # Remove repo if desired + if [ "x${GRADLE_CLEAR_REPO}" != "x" ]; then + rm -rf "${S2I_ARTIFACTS_DIR}/gradle" + check_error "Cannot remove local Gradle repository ${S2I_ARTIFACTS_DIR}/gradle" $? + fi + + cd ${old_dir} +} + + + +# ========================================================================= +# Main + +echo "==================================================================" +echo "Starting S2I Java Build ....." +[ -d "${DEPLOYMENTS_DIR}" ] || mkdir -p "${DEPLOYMENTS_DIR}" +if [ -f "${S2I_SOURCE_DIR}/pom.xml" ]; then + echo "S2I source build for Maven detected" + build_dir=$(get_maven_output_dir) + check_error "Cannot get output dir: $build_dir" $? + # If a pom.xml is present use maven + setup_maven + build_maven ${build_dir} ${DEPLOYMENTS_DIR} +elif [ -f "${S2I_SOURCE_DIR}/Dockerfile" ]; then + # This is a S2I binary build coming from fabric8-maven-plugin + echo "S2I binary build from fabric8-maven-plugin detected" + if [ -d "${S2I_SOURCE_DIR}/maven" ]; then + binary_dir="${S2I_SOURCE_DIR}/maven" + elif [ -d "${S2I_SOURCE_DIR}/deployments" ]; then + binary_dir="${S2I_SOURCE_DIR}/deployments" + elif [ $(find "${S2I_SOURCE_DIR}" -maxdepth 1 -type d | grep -v -e "^${S2I_SOURCE_DIR}$" | wc -l) == 1 ]; then + # Found a single directory, take this + binary_dir=$(find "${S2I_SOURCE_DIR}" -maxdepth 1 -type d | grep -v -e "^${S2I_SOURCE_DIR}$") + else + check_error "No single directory found in ${S2I_SOURCE_DIR} but:\n $(ls -l ${S2I_SOURCE_DIR})" 1 + fi + echo "Copying binaries from ${binary_dir} to ${DEPLOYMENTS_DIR} ..." + copy_dir ${binary_dir} ${DEPLOYMENTS_DIR} + check_error "copying ${binary_dir} to ${DEPLOYMENTS_DIR}" $? + +elif ls ${S2I_SOURCE_DIR}/*.gradle* &> /dev/null; then + echo "S2I source build for Gradle detected, due to presence of a *.gradle* in ${S2I_SOURCE_DIR}" + build_dir=$(get_gradle_output_dir) + check_error "Cannot get output dir: $build_dir" $? + build_gradle ${build_dir} ${DEPLOYMENTS_DIR} + +else + echo "S2I source build with plain binaries detected" + if [ -d "${S2I_SOURCE_DIR}/deployments" ]; then + default_binary_dir="${S2I_SOURCE_DIR}/deployments" + else + default_binary_dir="${S2I_SOURCE_DIR}" + fi + binary_dir="${ARTIFACT_DIR:-${default_binary_dir}}" + # Assuming that the source already contains compiled artefacts + echo "Copying binaries from ${binary_dir} to ${DEPLOYMENTS_DIR} ..." + copy_dir ${binary_dir} ${DEPLOYMENTS_DIR} + check_error "copying ${binary_dir} to ${DEPLOYMENTS_DIR}" $? +fi + +# check if this is a fat jar executable archive. SpringBoot fat jars can be exploded +echo "Checking for fat jar archive..." +old_dir=`pwd` +cd "${DEPLOYMENTS_DIR}" +nr_jars=`ls *.jar 2>/dev/null | grep -v '^original-' | wc -l | tr -d '[[:space:]]'` +if [ ${nr_jars} = 1 ]; then + single_jar=`ls *.jar | grep -v '^original-'` + echo "Found ${single_jar}..." + nr_devtools=`unzip -l "${single_jar}" 2>/dev/null | grep -e 'spring-boot-devtools-.*\.jar' | wc -l | tr -d '[[:space:]]'` + if [ ${nr_devtools} = 1 ]; then + main_class=`unzip -p "${single_jar}" META-INF/MANIFEST.MF | sed -n 's/Main-Class: \(.*\)$/\1/p' | tr -d '[[:space:]]'` + echo "Found main class ${main_class}" + if [[ "${main_class}" =~ org.springframework.boot.loader. ]]; then + # explosion!!! + echo "SpringBoot executable jar detected, exploding..." + unzip -q "${single_jar}" + # remove fat jar, run script will setup main class, etc. for run-java.sh + rm "${single_jar}" + # to support 'oc rsh', set group permissions to be same as the user and set the group to + # the root group + chgrp -R 0 . + chmod -R g=u . + fi + fi +fi +cd "${old_dir}" + +# Remove java temporary hsperfdata directory owned by the jboss user +rm -rf /tmp/hsperfdata_jboss + +echo "... done" diff --git a/java/images/fedora-java8/s2i/run b/java/images/fedora-java8/s2i/run new file mode 100644 index 00000000..7f6fb0e6 --- /dev/null +++ b/java/images/fedora-java8/s2i/run @@ -0,0 +1,61 @@ +#!/bin/bash + +# Command line arguments given to this script +args="$*" + +# Global S2I variable setup +source `dirname "$0"`/s2i-setup + +# Always include jolokia-opts, which can be empty if switched off via env +JAVA_OPTIONS="${JAVA_OPTIONS:+${JAVA_OPTIONS} }$(/opt/jolokia/jolokia-opts) $(/opt/prometheus/prometheus-opts)" + +# Temporary options variable until the harmonization hawt-app PR #5 has been applied (hopefully) +JVM_ARGS="${JVM_ARGS:+${JVM_ARGS} }${JAVA_OPTIONS}" +export JAVA_OPTIONS JVM_ARGS + +# support JBoss Tools OpenShift debug environment variables +export JAVA_DEBUG="${JAVA_DEBUG:-${DEBUG}}" +if [ "x${JAVA_DEBUG}" != x ]; then + export JAVA_DEBUG_PORT="${JAVA_DEBUG_PORT:-${DEBUG_PORT}}" +fi +# SpringBoot also uses DEBUG variable, so shade it with SPRINGBOOT_DEBUG variable +if [ "x${SPRINGBOOT_DEBUG}" != x ]; then + export DEBUG="${SPRINGBOOT_DEBUG}" +else + unset DEBUG +fi + +# check for SpringBoot exploded archive +if [ -f "${DEPLOYMENTS_DIR}/META-INF/MANIFEST.MF" ]; then + echo "SpringBoot exploded archive detected..." + if [ "x${JAVA_DEBUG}" != x ]; then + # setup classpath and start class as main class + if [ "x${JAVA_CLASSPATH}" = x ]; then + JAVA_CLASSPATH="${DEPLOYMENTS_DIR}/BOOT-INF/lib/*" + else + JAVA_CLASSPATH="${DEPLOYMENTS_DIR}/BOOT-INF/lib/*:${JAVA_CLASSPATH}" + fi + export JAVA_CLASSPATH="${DEPLOYMENTS_DIR}/BOOT-INF/classes/:${JAVA_CLASSPATH}" + # setup start class as main class + main_class=`sed -n 's/Start-Class: \(.*\)$/\1/p' "${DEPLOYMENTS_DIR}/META-INF/MANIFEST.MF" | tr -d '[[:space:]]'` + fi + # default to SpringBoot's Main-Class + if [ "x${main_class}" = x ]; then + main_class=`sed -n 's/Main-Class: \(.*\)$/\1/p' "${DEPLOYMENTS_DIR}/META-INF/MANIFEST.MF" | tr -d '[[:space:]]'` + fi + echo "Starting SpringBoot application with main class ${main_class}" + export JAVA_MAIN_CLASS="${main_class}" +fi + +# Update the jboss user UID entry in /etc/passwd +sed "/^jboss/s/[^:]*/$(id -u)/3" /etc/passwd > /tmp/passwd +cat /tmp/passwd > /etc/passwd +rm /tmp/passwd + +if [ -f "${DEPLOYMENTS_DIR}/bin/run.sh" ]; then + echo "Starting the application using the bundled ${DEPLOYMENTS_DIR}/bin/run.sh ..." + exec ${DEPLOYMENTS_DIR}/bin/run.sh $args ${JAVA_ARGS} +else + echo "Starting the Java application using /opt/run-java/run-java.sh ..." + exec /opt/run-java/run-java.sh $args ${JAVA_ARGS} +fi diff --git a/java/images/fedora-java8/s2i/s2i-setup b/java/images/fedora-java8/s2i/s2i-setup new file mode 100644 index 00000000..fef03cb2 --- /dev/null +++ b/java/images/fedora-java8/s2i/s2i-setup @@ -0,0 +1,6 @@ +# Local vars setup with defaults +S2I_DESTINATION=${S2I_DESTINATION:-/tmp} +S2I_SOURCE_DIR="${S2I_DESTINATION}/src" +S2I_ARTIFACTS_DIR="${S2I_DESTINATION}/artifacts" +DEPLOYMENTS_DIR="${DEPLOYMENTS_DIR:-/deployments}" +RUN_JAVA_DIR=/opt/run-java diff --git a/java/images/fedora-java8/s2i/save-artifacts b/java/images/fedora-java8/s2i/save-artifacts new file mode 100644 index 00000000..c0cc9b67 --- /dev/null +++ b/java/images/fedora-java8/s2i/save-artifacts @@ -0,0 +1,10 @@ +#!/bin/sh + +. `dirname "$0"`/s2i-setup + +# Tar up maven repository for reuse in an incremental build +if [ -d "${S2I_ARTIFACTS_DIR}/m2" ]; then + cd ${S2I_ARTIFACTS_DIR} + tar cf - m2 + cd - +fi diff --git a/java/images/fedora-java8/s2i/usage b/java/images/fedora-java8/s2i/usage new file mode 100644 index 00000000..342b8ba9 --- /dev/null +++ b/java/images/fedora-java8/s2i/usage @@ -0,0 +1,2 @@ +#!/bin/sh +cat $(dirname $0)/usage.txt diff --git a/java/images/fedora-java8/settings.xml b/java/images/fedora-java8/settings.xml new file mode 100644 index 00000000..fa0555ab --- /dev/null +++ b/java/images/fedora-java8/settings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/java/templates/Dockerfile b/java/templates/Dockerfile index c274ddf8..18552285 100644 --- a/java/templates/Dockerfile +++ b/java/templates/Dockerfile @@ -35,10 +35,10 @@ RUN yum install -y --enablerepo=jboss-rhel-rhscl rh-maven33-maven \ && yum clean all \ && ln -s /opt/rh/rh-maven33/root/bin/mvn /usr/local/bin/mvn {{??}} -# Dowload Maven from Apache +# Install Java package & download Maven from Apache RUN yum install -y \ - java-1.8.0-openjdk-{{= fp.config.base.version.java}} \ - java-1.8.0-openjdk-devel-{{= fp.config.base.version.java}} \ + java-1.8.0-openjdk{{= fp.config.base.version.java}} \ + java-1.8.0-openjdk-devel{{= fp.config.base.version.java}} \ && curl https://archive.apache.org/dist/maven/maven-3/{{= mavenVersion }}/binaries/apache-maven-{{= mavenVersion }}-bin.tar.gz | \ tar -xzf - -C /opt \ && ln -s /opt/apache-maven-{{= mavenVersion }} /opt/maven \