├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── DEVELOPING.md
├── Dockerfile.builder
├── LICENSE
├── README.md
├── checkstyle
└── checkstyle-suppressions.xml
├── cloudbuild.yaml
├── java-runtimes-common
├── README.md
├── mvn-gcloud-image
│ └── Dockerfile
└── test-spring-application
│ ├── README.md
│ ├── pom.xml
│ └── src
│ └── main
│ ├── appengine
│ └── app.yaml
│ ├── docker
│ └── Dockerfile
│ ├── java
│ └── com
│ │ └── google
│ │ └── cloud
│ │ └── runtimes
│ │ ├── Application.java
│ │ ├── DeploymentTokenController.java
│ │ ├── ExceptionController.java
│ │ ├── HelloController.java
│ │ ├── LoggingTestController.java
│ │ ├── MonitoringTestController.java
│ │ ├── config
│ │ └── GcpConfiguration.java
│ │ └── stackdriver
│ │ └── StackDriverMonitoringService.java
│ ├── kubernetes
│ └── openjdk-spring-boot.yaml.in
│ └── resources
│ └── application.properties
├── openjdk-common
├── pom.xml
└── src
│ └── main
│ ├── assembly
│ └── assembly.xml
│ └── docker
│ ├── docker-entrypoint.bash
│ ├── setup-env.d
│ ├── 05-utils.bash
│ ├── 10-platform-env.bash
│ ├── 25-profiler-env.bash
│ └── 30-java-env.bash
│ ├── shutdown
│ ├── shutdown-env.bash
│ └── shutdown-wrapper.bash
│ └── sid.list
├── openjdk-test-common
├── pom.xml
└── src
│ ├── main
│ └── assembly
│ │ └── assembly.xml
│ └── test
│ └── resources
│ ├── structure.yaml
│ └── workspace
│ ├── entrypoint-args-only.bash
│ ├── entrypoint-default.bash
│ ├── entrypoint-setup.bash
│ ├── setup-java.bash
│ ├── setup-platform.bash
│ ├── setup-profiler.bash
│ ├── shutdown-env.bash
│ └── test-denylisted-pkgs.bash
├── openjdk11
├── pom.xml
└── src
│ ├── main
│ └── docker
│ │ └── Dockerfile
│ └── test
│ └── resources
│ ├── jdk11-compilation-test
│ ├── .gitignore
│ ├── com.google.greetings
│ │ ├── com
│ │ │ └── google
│ │ │ │ └── greetings
│ │ │ │ └── Main.java
│ │ └── module-info.java
│ ├── com.google.world
│ │ ├── com
│ │ │ └── google
│ │ │ │ └── world
│ │ │ │ └── World.java
│ │ └── module-info.java
│ └── compile-and-run.sh
│ └── openjdk11-structure.yaml
├── openjdk8
├── pom.xml
└── src
│ ├── main
│ └── docker
│ │ └── Dockerfile
│ └── test
│ └── resources
│ └── openjdk8-structure.yaml
├── pom.xml
└── scripts
├── ae_integration_test.sh
├── build.sh
├── ci-build.sh
├── deploy-check-openjdk8.sh
├── gcloud-init.sh
├── gke_cluster_cleanup.yaml
├── gke_integration_test.sh
├── integration_test.sh
├── integration_test.yaml
├── integration_test_cleanup.yaml
├── local_runtimes_common_integration_test.sh
├── local_shutdown_test.sh
├── release-openjdk.sh
└── structure_test.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # docker specific
2 | docker/lib/
3 | docker/jetty/
4 |
5 | # maven
6 | target
7 | *.versionsBackup
8 | *.releaseBackup
9 |
10 | # common junk
11 | *.log
12 | *.diff
13 | *.patch
14 | *.sw[a-z0-9]
15 | *.bak
16 | *.backup
17 | *.debug
18 | *.dump
19 | *~
20 | ~*
21 |
22 | # eclipse
23 | .project
24 | .settings
25 | .classpath
26 |
27 | # intellij / idea
28 | *.iml
29 | *.ipr
30 | *.iws
31 | .idea
32 |
33 | # netbeans
34 | /nbproject
35 |
36 | # Mac filesystem dust
37 | .DS_Store
38 |
39 | # merge tooling
40 | *.orig
41 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2016 Google Inc. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | sudo: required
16 |
17 | language: java
18 |
19 | services:
20 | - docker
21 |
22 | jdk:
23 | - oraclejdk8
24 |
25 | # skip the install step
26 | install: true
27 | script: mvn --batch-mode clean verify
28 |
29 | branches:
30 | only:
31 | - master
32 |
33 | dist: trusty
34 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to become a contributor and submit your own code
2 |
3 | ## Contributor License Agreements
4 |
5 | We'd love to accept your patches! Before we can take them, we have to jump a couple of legal hurdles.
6 |
7 | Please fill out either the individual or corporate Contributor License Agreement (CLA).
8 |
9 | * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html).
10 | * If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).
11 |
12 | Follow either of the two links above to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll be able to accept your pull requests.
13 |
14 | ## Contributing A Patch
15 |
16 | 1. Submit an issue describing your proposed change to the repo in question.
17 | 1. The repo owner will respond to your issue promptly.
18 | 1. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above).
19 | 1. Fork the desired repo, develop and test your code changes.
20 | 1. Submit a pull request.
21 |
--------------------------------------------------------------------------------
/DEVELOPING.md:
--------------------------------------------------------------------------------
1 | # Developing
2 |
3 | This document contains instructions on how to build and test this image.
4 |
5 | # Building the image
6 |
7 | ### Local build
8 | To build the image you need git, docker (your user needs to be part of the ``docker`` group to run docker without sudo) and maven installed:
9 | ```
10 | $ git clone https://github.com/GoogleCloudPlatform/openjdk-runtime.git
11 | $ cd openjdk-runtime
12 |
13 | # build all images
14 | $ mvn clean install
15 |
16 | # only build the openjdk:8 image
17 | $ mvn clean install --also-make --projects openjdk8
18 |
19 | # only build the openjdk:11 image
20 | $ mvn clean install --also-make --projects openjdk11
21 | ```
22 | These commands build the `openjdk` image with tags for each JDK version (`openjdk:8` and `openjdk:11`).
23 |
24 | ### Cloud build
25 | To build using the [Google Cloud Container Builder](https://cloud.google.com/container-builder/docs/overview),
26 | you need to have the [Google Cloud SDK](https://cloud.google.com/sdk/) installed locally. We provide a script to make this more convenient.
27 | ```
28 | # the following commands will build and push an image named "gcr.io/my-project/openjdk:8"
29 | $ PROJECT_ID=my-project
30 | $ MODULE_TO_BUILD=openjdk8 # only builds the openjdk:8 image
31 | $ ./scripts/build.sh -p $PROJECT_ID -m $MODULE_TO_BUILD
32 | ```
33 |
34 | If you would like to simulate the cloud build locally, pass in the `--local` argument.
35 | ```
36 | $ PROJECT_ID=my-project
37 | $ MODULE_TO_BUILD=openjdk8 # only builds the openjdk:8 image
38 | $ ./scripts/build.sh -p $PROJECT_ID -m $MODULE_TO_BUILD --local
39 | ```
40 |
41 | The configured Cloud Build execution will build the OpenJDK docker container, then create and teardown various GCP resources for integration testing.
42 | Before running, make sure you have done all of the following:
43 |
44 | * enabled the Cloud Container Builder API
45 | * initialized App Engine for your GCP project (run `gcloud app create`), and successfully deployed at least once
46 | * provided the Container Builder Service account (cloudbuild.gserviceaccount.com) with the appropriate permissions needed to deploy App Engine applications and create GKE clusters.
47 | * This includes at least the "App Engine Admin" and "Cloud Container Builder" roles, but simply adding the "Project Editor" role works fine as well.
48 |
49 | # Running Tests
50 | Integration tests can be run via [Google Cloud Container Builder](https://cloud.google.com/container-builder/docs/overview).
51 | These tests deploy a sample test application to App Engine and to Google Kubernetes Engine using the provided runtime image, and
52 | exercise various integrations with other GCP services. Note that the image under test must be pushed
53 | to a gcr.io repository before the integration tests can run.
54 |
55 | ```bash
56 | $ RUNTIME_IMAGE=gcr.io/my-project-id/openjdk:my-tag
57 | $ gcloud docker -- push $RUNTIME_IMAGE
58 | ```
59 |
60 | **Run ALL integration tests (Local Docker, App Engine, Google Kubernetes Engine):**
61 | ```bash
62 | $ ./scripts/integration_test.sh $RUNTIME_IMAGE
63 | ```
64 |
65 | **Run ONLY Local Docker integration tests:**
66 | ```bash
67 | $ ./scripts/local_runtimes_common_integration_test.sh $RUNTIME_IMAGE
68 | ```
69 |
70 | **Run ONLY Local shutdown tests:**
71 | ```bash
72 | $ ./scripts/local_shutdown_test.sh $RUNTIME_IMAGE
73 | ```
74 |
75 |
76 | **Run ONLY App Engine flexible environment integration tests:**
77 | ```bash
78 | $ ./scripts/ae_integration_test.sh $RUNTIME_IMAGE
79 | ```
80 |
81 | **Run ONLY Kubernetes Engine (GKE) integration tests:**
82 | ```bash
83 | $ ./scripts/gke_integration_test.sh $RUNTIME_IMAGE
84 | ```
85 |
--------------------------------------------------------------------------------
/Dockerfile.builder:
--------------------------------------------------------------------------------
1 | FROM gcr.io/cloud-builders/javac
2 | ARG MAVEN_VERSION=3.5.0
3 | ARG USER_HOME_DIR="/root"
4 | ARG SHA=beb91419245395bd69a4a6edad5ca3ec1a8b64e41457672dc687c173a495f034
5 | ARG BASE_URL=https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries
6 |
7 | RUN apt-get update -qqy && apt-get install -qqy curl \
8 | && mkdir -p /usr/share/maven /usr/share/maven/ref \
9 | && curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-$MAVEN_VERSION-bin.tar.gz \
10 | && echo "${SHA} /tmp/apache-maven.tar.gz" | sha256sum -c - \
11 | && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
12 | && rm -f /tmp/apache-maven.tar.gz \
13 | && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn \
14 | # clean up build packages
15 | && apt-get remove -qqy --purge curl \
16 | && rm /var/lib/apt/lists/*_*
17 |
18 | ENV M2_HOME /usr/share/maven
19 |
20 | ENTRYPOINT ["mvn"]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Google Cloud Platform OpenJDK Docker Image
3 |
4 | This repository contains the source for the Google-maintained OpenJDK [docker](https://docker.com) image. This image can be used as the base image for running Java applications on [Google App Engine Flexible Environment](https://cloud.google.com/appengine/docs/flexible/java/) and [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine).
5 |
6 | ## Repository/Tag Details
7 | Supported images/tags include:
8 | * `gcr.io/google-appengine/openjdk:8`
9 |
10 | ## App Engine Flexible Environment
11 | When using App Engine Flexible, you can use the runtime without worrying about Docker by specifying `runtime: java` in your `app.yaml`:
12 | ```yaml
13 | runtime: java
14 | env: flex
15 | ```
16 | The runtime image `gcr.io/google-appenine/openjdk:8` will be automatically selected if you are attempting to deploy a JAR (`*.jar` file).
17 |
18 | To select a jdk version, use the `runtime_config.jdk` field in app.yaml. Supported JDK versions include `openjdk8` and `openjdk11`.
19 | ```yaml
20 | runtime: java
21 | env: flex
22 | runtime_config:
23 | jdk: openjdk8
24 | ```
25 |
26 | If you want to use the image as a base for a custom runtime, you can specify `runtime: custom` in your `app.yaml` and then
27 | write the Dockerfile like this:
28 |
29 | ```dockerfile
30 | FROM gcr.io/google-appengine/openjdk
31 | COPY your-application.jar $APP_DESTINATION
32 | ```
33 |
34 | That will add the JAR in the correct location for the Docker container.
35 |
36 | Once you have this configuration, you can use the Google Cloud SDK to deploy this directory containing the 2 configuration files and the JAR using:
37 | ```
38 | gcloud app deploy app.yaml
39 | ```
40 |
41 | ## Kubernetes Engine & other Docker hosts
42 | For other Docker hosts, you'll need to create a Dockerfile based on this image that copies your application code and installs dependencies. For example:
43 |
44 | ```dockerfile
45 | FROM gcr.io/google-appengine/openjdk
46 | COPY your-application.jar $APP_DESTINATION
47 | ```
48 | You can then build the docker container using `docker build` or [Google Cloud Container Builder](https://cloud.google.com/container-builder/docs/).
49 | By default, the CMD is set to run the application JAR. You can change this by specifying your own `CMD` or `ENTRYPOINT`.
50 |
51 | ### Container Memory Limits
52 | The runtime will try to detect the container memory limit by looking at the `/sys/fs/cgroup/memory/memory.limit_in_bytes` file, which is automatically mounted by Docker. However, this may not work with other container runtimes. In those cases, to help the runtime compute accurate JVM memory defaults when running on Kubernetes, you can indicate memory limit through the [Downward API](https://kubernetes.io/docs/tasks/configure-pod-container/environment-variable-expose-pod-information).
53 |
54 | To do so add an environment variable named `KUBERNETES_MEMORY_LIMIT` *(This name is subject to change)* with the value `limits.memory` and the name of your container.
55 | For example:
56 |
57 | ```yaml
58 | apiVersion: v1
59 | kind: Pod
60 | metadata:
61 | name: dapi-envars-resourcefieldref
62 | spec:
63 | containers:
64 | - name: java-kubernetes-container
65 | image: gcr.io/google-appengine/openjdk
66 | resources:
67 | requests:
68 | memory: "32Mi"
69 | limits:
70 | memory: "64Mi"
71 | env:
72 | - name: KUBERNETES_MEMORY_LIMIT
73 | valueFrom:
74 | resourceFieldRef:
75 | containerName: java-kubernetes-container
76 | resource: limits.memory
77 | ```
78 |
79 | ## The Default Entry Point
80 | Any arguments passed to the entry point that are not executable are treated as arguments to the java command:
81 | ```
82 | $ docker run openjdk -jar /usr/share/someapplication.jar
83 | ```
84 |
85 | Any arguments passed to the entry point that are executable replace the default command, thus a shell could
86 | be run with:
87 | ```
88 | > docker run -it --rm openjdk bash
89 | root@c7b35e88ff93:/#
90 | ```
91 |
92 | ## Entry Point Features
93 | The entry point for the openjdk8 image is [docker-entrypoint.bash](https://github.com/GoogleCloudPlatform/openjdk-runtime/blob/master/openjdk-common/src/main/docker/docker-entrypoint.bash), which does the processing of the passed command line arguments to look for an executable alternative or arguments to the default command (java).
94 |
95 | If the default command (java) is used, then the entry point sources the [setup-env.d/](https://github.com/GoogleCloudPlatform/openjdk-runtime/tree/master/openjdk-common/src/main/docker/setup-env.d), which looks for supported features to be enabled and/or configured. The following table indicates the environment variables that may be used to enable/disable/configure features, any default values if they are not set:
96 |
97 | |Env Var | Description | Type | Default |
98 | |------------------------------------|---------------------|----------|---------------------------------------------|
99 | |`PROFILER_ENABLE` | Stackdriver Profiler| boolean | `false` |
100 | |`TMPDIR` | Temporary Directory | dirname | |
101 | |`JAVA_TMP_OPTS` | JVM tmpdir args | JVM args | `-Djava.io.tmpdir=${TMPDIR}` |
102 | |`GAE_MEMORY_MB` | Available memory | size | Set by GAE or `/proc/meminfo`-400M |
103 | |`HEAP_SIZE_RATIO` | Memory for the heap | percent | 80 |
104 | |`HEAP_SIZE_MB` | Available heap | size | `${HEAP_SIZE_RATIO}`% of `${GAE_MEMORY_MB}` |
105 | |`JAVA_HEAP_OPTS` | JVM heap args | JVM args | `-Xms${HEAP_SIZE_MB}M -Xmx${HEAP_SIZE_MB}M` |
106 | |`JAVA_GC_OPTS` | JVM GC args | JVM args | `-XX:+UseG1GC` plus configuration |
107 | |`JAVA_USER_OPTS` | JVM other args | JVM args | |
108 | |`JAVA_OPTS` | JVM args | JVM args | See below |
109 | |`SHUTDOWN_LOGGING_THREAD_DUMP` | Shutdown thread dump| boolean | `false` |
110 | |`SHUTDOWN_LOGGING_HEAP_INFO` | Shutdown heap info | boolean | `false` |
111 | |`SHUTDOWN_LOGGING_SAMPLE_THRESHOLD` | Shutdown sampling | percent | 100 |
112 |
113 | If not explicitly set, `JAVA_OPTS` is defaulted to
114 | ```
115 | JAVA_OPTS:=-showversion \
116 | ${JAVA_TMP_OPTS} \
117 | ${PROFILER_AGENT} \
118 | ${JAVA_HEAP_OPTS} \
119 | ${JAVA_GC_OPTS} \
120 | ${JAVA_USER_OPTS}
121 | ```
122 |
123 | The command line executed is effectively (where $@ are the args passed into the docker entry point):
124 | ```
125 | java $JAVA_OPTS "$@"
126 | ```
127 |
128 | ### JVM Shutdown Diagnostics
129 |
130 | This feature is not enabled by default.
131 |
132 | Sometimes it's necessary to obtain diagnostic information when the JVM is stopped using `SIGTERM` or `docker stop`.
133 | This may happen on App Engine flexible environment, when the autohealer decides to kill unhealthy VMs that have
134 | an app that is unresponsive due to a deadlock or high load and stopped returning requests, including health checks.
135 |
136 | To help diagnose such situations the runtime provides support for outputting a thread dump and/or
137 | heap info upon JVM shutdown forced by the `TERM` signal.
138 |
139 | The following environment variables should be used to enable app container shutdown reporting (must be set to `true` or `false`):
140 |
141 | `SHUTDOWN_LOGGING_THREAD_DUMP` - output thread dump
142 |
143 | `SHUTDOWN_LOGGING_HEAP_INFO` - output heap information
144 |
145 | If enabled, the runtime provides a wrapper for the JVM that traps `SIGTERM`, and runs debugging tools on the JVM
146 | to emit the thread dump and heap information to stdout.
147 |
148 | If you're running many VMs, sampling is supported by using the environment variable `SHUTDOWN_LOGGING_SAMPLE_THRESHOLD`
149 | which is an integer between 0 and 100. 0 means no VMs report logs, 100 means all VMs report logs.
150 | (If this env var is not set, we default to reporting for all VMs).
151 |
152 | ## The Default Command
153 | The default command will attempt to run `app.jar` in the current working directory.
154 | It's equivalent to:
155 | ```
156 | $ docker run openjdk java -jar app.jar
157 | Error: Unable to access jarfile app.jar
158 | ```
159 | The error is normal because the default command is designed for child containers that have a Dockerfile definition like this:
160 | ```
161 | FROM openjdk
162 | ADD my_app_0.0.1.jar app.jar
163 | ```
164 | # Development Guide
165 |
166 | * See [instructions](DEVELOPING.md) on how to build and test this image.
167 |
168 | # Contributing changes
169 |
170 | * See [CONTRIBUTING.md](CONTRIBUTING.md)
171 |
172 | ## Licensing
173 |
174 | * See [LICENSE.md](LICENSE)
175 |
--------------------------------------------------------------------------------
/checkstyle/checkstyle-suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/cloudbuild.yaml:
--------------------------------------------------------------------------------
1 | # Cloud Builder pipeline
2 | # https://cloud.google.com/container-builder/docs/overview
3 |
4 | steps:
5 | # Build the openjdk image
6 | - name: gcr.io/cloud-builders/docker
7 | args: ['build', '.', '-f', 'Dockerfile.builder', '-t', 'builder']
8 | - name: 'builder'
9 | args:
10 | - 'clean'
11 | - 'install'
12 | - '--batch-mode'
13 | - '-Ddocker.image.name=${_IMAGE}'
14 | # only build the specified module
15 | - '--projects=${_MODULE}'
16 | - '--also-make'
17 | id: 'MVN_PACKAGE'
18 |
19 | # temporarily this test is turned off while we restructure the testing infrastructure, to enable
20 | # quicker release process
21 |
22 | ## Tag and push the openjdk image to a staging repository for integration testing
23 | #- name: 'gcr.io/cloud-builders/docker'
24 | # args: ['tag', '${_IMAGE}', '${_STAGING_IMAGE}']
25 | # id: 'TAG_STAGING_IMG'
26 | #- name: 'gcr.io/cloud-builders/docker'
27 | # args: ['push', '${_STAGING_IMAGE}']
28 | # id: 'PUSH_STAGING_IMG'
29 | #
30 | ## Build a 'builder' image for running integration tests
31 | #- name: 'gcr.io/cloud-builders/docker'
32 | # args: ['build', '--tag=mvn-gcloud', 'java-runtimes-common/mvn-gcloud-image']
33 | # waitFor: ['-']
34 | # id: 'BUILD_MVN_GCLOUD'
35 | #
36 | ## Execute integration tests
37 | #- name: 'mvn-gcloud'
38 | # entrypoint: 'scripts/integration_test.sh'
39 | # args: ['${_STAGING_IMAGE}']
40 | # id: 'INTEGRATION_TEST'
41 |
42 | images: ['${_IMAGE}']
43 |
--------------------------------------------------------------------------------
/java-runtimes-common/README.md:
--------------------------------------------------------------------------------
1 | # Java Runtimes Common
2 |
3 | This module contains code that is common across multiple java runtimes.
--------------------------------------------------------------------------------
/java-runtimes-common/mvn-gcloud-image/Dockerfile:
--------------------------------------------------------------------------------
1 | # Dockerfile for building a test container that includes java, maven, and the Google Cloud SDK.
2 | # This is intended to be used as part of a Google Cloud Container Builder build.
3 |
4 | FROM gcr.io/cloud-builders/mvn:3.3.9-jdk-8
5 |
6 | ARG CLOUD_SDK_VERSION=172.0.0
7 |
8 | RUN apt-get -y update && \
9 | apt-get -y install gcc python2.7 python-dev python-setuptools curl wget ca-certificates gettext-base && \
10 |
11 | # Setup Google Cloud SDK (latest)
12 | mkdir -p /builder && \
13 | wget -qO- "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz" | tar zxv -C /builder && \
14 | CLOUDSDK_PYTHON="python2.7" /builder/google-cloud-sdk/install.sh \
15 | --usage-reporting=false \
16 | --bash-completion=false \
17 | --disable-installation-options && \
18 |
19 | /builder/google-cloud-sdk/bin/gcloud config set component_manager/disable_update_check 1 && \
20 |
21 | # Kubernetes configuration
22 | /builder/google-cloud-sdk/bin/gcloud config set compute/zone us-east1-b && \
23 | /builder/google-cloud-sdk/bin/gcloud components install kubectl -q
24 |
25 | ENV PATH=/builder/google-cloud-sdk/bin/:$PATH
26 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/README.md:
--------------------------------------------------------------------------------
1 | # Test Application
2 |
3 | This is a test application to be used in testing the Java Runtimes containers. It implements a set
4 | of http endpoints which exercise integrations with various Stackdriver APIs, in line with the
5 | [Runtimes-common integration test framework](https://github.com/GoogleCloudPlatform/runtimes-common/tree/master/integration_tests#tests).
6 |
7 | The test application is a simple [Spring Boot](https://projects.spring.io/spring-boot/) application,
8 | which can be built in several different ways.
9 |
10 | ## Supported profiles
11 | ### Runtime staging profiles
12 | Runtime staging profiles can be mixed & matched with deployment profiles.
13 |
14 | **Java runtime profile (default)** - prepares files in the `target/deploy` directory for deployment to the default Java runtime on App Engine Flexible:
15 | ```bash
16 | mvn install -Pruntime.java
17 | ```
18 | **Custom runtime profile** - prepares files in the `target/deploy` directory for deployment to a custom runtime on App Engine Flexible:
19 | - When using this profile, the `app.deploy.image` property must be specified as well.
20 | ```bash
21 | mvn install -Pruntime.custom -Dapp.deploy.image=gcr.io/google-appengine/openjdk
22 | ```
23 |
24 | ### Deployment profiles
25 | Deployment profiles can be mixed & matched with runtime staging profiles.
26 |
27 | **JAR deployment profile (default)** - packages the application as an executable JAR that embeds a web server.
28 | ```bash
29 | mvn install -Pdeploy.jar
30 | ```
31 | **WAR deployment profile** - packages the application as a WAR file that can be deployed to a web server instance.
32 | ```bash
33 | mvn install -Pdeploy.war
34 | ```
35 |
36 |
37 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.google.cloud.runtimes
8 | test-spring-application
9 | 1.0.0
10 | ${packaging.type}
11 |
12 | Test Spring application for java runtimes
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 1.5.1.RELEASE
18 |
19 |
20 |
21 | UTF-8
22 | UTF-8
23 | 1.8
24 | ${java.version}
25 | ${java.version}
26 | default_deployment_token
27 | jar
28 | java
29 |
30 |
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-web
35 |
36 |
37 | com.google.cloud
38 | google-cloud-monitoring
39 | 0.22.0-alpha
40 |
41 |
42 | com.google.cloud
43 | google-cloud-logging
44 | 1.4.0
45 |
46 |
47 |
48 |
49 |
50 |
51 | org.springframework.boot
52 | spring-boot-maven-plugin
53 |
54 | app
55 | ${project.build.directory}/deploy
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-resources-plugin
61 | 3.0.2
62 |
63 |
64 | copy-app-yaml
65 | prepare-package
66 |
67 | copy-resources
68 |
69 |
70 | ${project.build.directory}/deploy
71 |
72 |
73 | ${basedir}/src/main/appengine
74 | true
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | deploy.jar
87 |
88 | true
89 |
90 |
91 | jar
92 |
93 |
94 |
95 | deploy.war
96 |
97 | war
98 |
99 |
100 |
101 | org.springframework.boot
102 | spring-boot-starter-tomcat
103 | provided
104 |
105 |
106 |
107 |
108 |
109 | runtime.custom
110 |
111 | true
112 |
113 |
114 | custom
115 |
116 |
117 |
118 |
119 | org.apache.maven.plugins
120 | maven-resources-plugin
121 | 3.0.2
122 |
123 |
124 | copy-resources
125 | prepare-package
126 |
127 | copy-resources
128 |
129 |
130 | ${project.build.directory}/deploy
131 |
132 |
133 | ${basedir}/src/main/docker
134 | true
135 |
136 |
137 | ${basedir}/src/main/kubernetes
138 | false
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | runtime.java
151 |
152 | java
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/appengine/app.yaml:
--------------------------------------------------------------------------------
1 | runtime: @app.deploy.runtime@
2 | env: flex
3 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM @app.deploy.image@
2 | ADD app.jar app.jar
3 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/Application.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.boot.builder.SpringApplicationBuilder;
6 | import org.springframework.boot.web.support.SpringBootServletInitializer;
7 |
8 | @SpringBootApplication
9 | public class Application extends SpringBootServletInitializer {
10 | public static void main(String[] args) {
11 | SpringApplication.run(Application.class, args);
12 | }
13 |
14 | @Override
15 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
16 | return application.sources(Application.class);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/DeploymentTokenController.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | import static org.springframework.web.bind.annotation.RequestMethod.GET;
8 |
9 | @RestController
10 | public class DeploymentTokenController {
11 |
12 | @Value("${deployment.token}")
13 | private String deploymentToken;
14 |
15 | @RequestMapping(path = "/deployment.token", method = GET)
16 | public String deploymentToken() {
17 | return deploymentToken;
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/ExceptionController.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes;
2 |
3 | import org.springframework.web.bind.annotation.RequestBody;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | import static org.springframework.web.bind.annotation.RequestMethod.POST;
8 |
9 | @RestController
10 | public class ExceptionController {
11 |
12 | static class ExceptionRequest {
13 | public String token;
14 | }
15 |
16 | @RequestMapping(path = "/exception", method = POST)
17 | public void exception(@RequestBody ExceptionRequest request) {
18 | // Print a stack trace to stdout. This should be automatically registered to stackdriver error
19 | // reporting.
20 | new RuntimeException("Sample runtime exception for testing. Token from test driver request: "
21 | + request.token).printStackTrace();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/HelloController.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes;
2 |
3 | import org.springframework.web.bind.annotation.RequestMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | import static org.springframework.web.bind.annotation.RequestMethod.GET;
7 |
8 | @RestController
9 | public class HelloController {
10 |
11 | @RequestMapping(path = "/", method = GET)
12 | public String hello() {
13 | return "Hello World!";
14 | }
15 |
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/LoggingTestController.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes;
2 |
3 | import com.google.cloud.MonitoredResource;
4 | import com.google.cloud.logging.LogEntry;
5 | import com.google.cloud.logging.Logging;
6 | import com.google.cloud.logging.Payload;
7 | import com.google.cloud.logging.Severity;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.context.annotation.Lazy;
10 | import org.springframework.web.bind.annotation.RequestBody;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | import java.io.IOException;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 | import java.util.logging.Logger;
18 |
19 | import static org.springframework.web.bind.annotation.RequestMethod.POST;
20 |
21 | @RestController
22 | public class LoggingTestController {
23 |
24 | @Autowired
25 | @Lazy
26 | private Logging logging;
27 |
28 | private static Logger LOG = Logger.getLogger(LoggingTestController.class.getName());
29 |
30 | public static class LoggingTestRequest {
31 | private String level;
32 | private String log_name;
33 | private String token;
34 |
35 | public void setLevel(String level) {
36 | this.level = level;
37 | }
38 |
39 | public void setLog_name(String log_name) {
40 | this.log_name = log_name;
41 | }
42 |
43 | public void setToken(String token) {
44 | this.token = token;
45 | }
46 |
47 |
48 | @Override
49 | public String toString() {
50 | return "LoggingTestRequest{" +
51 | "level='" + level + '\'' +
52 | ", log_name='" + log_name + '\'' +
53 | ", token='" + token + '\'' +
54 | '}';
55 | }
56 | }
57 |
58 | @RequestMapping(path = "/logging_custom", method = POST)
59 | public String handleLoggingTestRequest(@RequestBody LoggingTestRequest loggingTestRequest) throws IOException, InterruptedException {
60 | LOG.info(String.valueOf(loggingTestRequest));
61 |
62 | List entries = new ArrayList<>();
63 | Payload.StringPayload payload = Payload.StringPayload.of(loggingTestRequest.token);
64 | Severity severity = Severity.valueOf(loggingTestRequest.level);
65 | LogEntry entry = LogEntry.newBuilder(payload)
66 | .setSeverity(severity)
67 | .setLogName(loggingTestRequest.log_name)
68 | .setResource(MonitoredResource.newBuilder("global").build())
69 | .build();
70 | entries.add(entry);
71 | logging.write(entries);
72 | LOG.info("Log written to StackDriver: " + entries);
73 | return "OK";
74 | }
75 |
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/MonitoringTestController.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes;
2 |
3 | import com.google.cloud.runtimes.stackdriver.StackDriverMonitoringService;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.beans.factory.annotation.Qualifier;
6 | import org.springframework.context.annotation.Lazy;
7 | import org.springframework.web.bind.annotation.RequestBody;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | import java.io.IOException;
12 | import java.util.logging.Logger;
13 |
14 | import static org.springframework.web.bind.annotation.RequestMethod.POST;
15 |
16 | @RestController
17 | public class MonitoringTestController {
18 |
19 | @Autowired
20 | @Lazy
21 | private StackDriverMonitoringService stackDriverMonitoringService;
22 |
23 | @Autowired
24 | @Qualifier("projectId")
25 | private String projectId;
26 |
27 | private static Logger LOG = Logger.getLogger(MonitoringTestController.class.getName());
28 |
29 | public static class MonitoringTestRequest {
30 | private String name;
31 | private Long token;
32 |
33 | public void setToken(Long token) {
34 | this.token = token;
35 | }
36 |
37 | public void setName(String name) {
38 | this.name = name;
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return "MonitoringTestRequest{" +
44 | "name='" + name + '\'' +
45 | ", token=" + token +
46 | '}';
47 | }
48 | }
49 |
50 | @RequestMapping(path = "/monitoring", method = POST)
51 | public String handleMonitoringRequest(@RequestBody MonitoringTestRequest monitoringTestRequest) throws IOException, InterruptedException {
52 | LOG.info(String.valueOf(monitoringTestRequest));
53 |
54 | stackDriverMonitoringService.createMetricAndInsertTestToken(projectId,
55 | monitoringTestRequest.name,
56 | monitoringTestRequest.token);
57 |
58 | return "OK";
59 | }
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/config/GcpConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes.config;
2 |
3 | import com.google.cloud.logging.Logging;
4 | import com.google.cloud.logging.LoggingOptions;
5 | import com.google.cloud.monitoring.v3.MetricServiceClient;
6 | import com.google.cloud.monitoring.v3.MetricServiceSettings;
7 | import com.google.cloud.monitoring.v3.stub.MetricServiceStub;
8 | import org.springframework.beans.factory.annotation.Qualifier;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.context.annotation.Lazy;
12 |
13 | import java.io.IOException;
14 |
15 | import static com.google.cloud.ServiceOptions.getDefaultProjectId;
16 |
17 | @Configuration
18 | public class GcpConfiguration {
19 |
20 | @Bean
21 | @Lazy
22 | public Logging getLogging() {
23 | LoggingOptions options = LoggingOptions.getDefaultInstance();
24 | return options.getService();
25 | }
26 |
27 | @Bean(name = "metricServiceClient")
28 | @Lazy
29 | public MetricServiceClient getMetricServiceClient() throws IOException {
30 | return MetricServiceClient.create();
31 | }
32 |
33 | @Qualifier("projectId")
34 | @Bean
35 | public String getProjectId() {
36 | return getDefaultProjectId();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/java/com/google/cloud/runtimes/stackdriver/StackDriverMonitoringService.java:
--------------------------------------------------------------------------------
1 | package com.google.cloud.runtimes.stackdriver;
2 |
3 | import com.google.api.Metric;
4 | import com.google.api.MetricDescriptor;
5 | import com.google.api.MonitoredResource;
6 | import com.google.cloud.monitoring.v3.MetricServiceClient;
7 | import com.google.cloud.monitoring.v3.stub.MetricServiceStub;
8 | import com.google.cloud.runtimes.config.GcpConfiguration;
9 | import com.google.monitoring.v3.*;
10 | import com.google.protobuf.util.Timestamps;
11 | import org.springframework.beans.BeansException;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.beans.factory.annotation.Value;
14 | import org.springframework.context.ApplicationContext;
15 | import org.springframework.context.ApplicationContextAware;
16 | import org.springframework.context.annotation.Lazy;
17 | import org.springframework.stereotype.Service;
18 |
19 | import java.io.IOException;
20 | import java.util.logging.Logger;
21 |
22 | @Service
23 | public class StackDriverMonitoringService {
24 |
25 | @Autowired
26 | private ApplicationContext applicationContext;
27 |
28 | @Value("${monitoring.write.retries}")
29 | private int maxRetries;
30 | private static Logger LOG = Logger.getLogger(StackDriverMonitoringService.class.getName());
31 |
32 |
33 | public void createMetricAndInsertTestToken(String projectId, String metricType, long metricValue) throws IOException {
34 | int retries = maxRetries;
35 | while (retries > 0) {
36 | try {
37 | CreateTimeSeriesRequest timeSeriesRequest = createTimeSeriesRequest(projectId, metricType, metricValue);
38 | getClient().createTimeSeries(timeSeriesRequest);
39 | LOG.info("Metric created with timeseries.");
40 | return;
41 | } catch (Exception e) {
42 | LOG.warning("error creating timeseries request, retrying..." + e.getClass() + ": " + e.getMessage());
43 | retries--;
44 | if (retries == 0) {
45 | throw new IllegalStateException("Failed to store timeseries after " + maxRetries + " attempts! Last error:", e);
46 | }
47 | }
48 | }
49 | }
50 |
51 | /**
52 | * This pairs up with the @Lazy annotation on {@link GcpConfiguration#getMetricServiceClient()}.
53 | * As MetricServiceClient methods are all `final` and that breaks the "@Autowire @Lazy" combination,
54 | * this is the only way to wire this bean lazily.
55 | */
56 | private MetricServiceClient getClient() {
57 | return (MetricServiceClient) applicationContext.getBean("metricServiceClient");
58 | }
59 |
60 | private CreateTimeSeriesRequest createTimeSeriesRequest(String projectId, String metricType, Long metricValue) {
61 | LOG.info("Creating time series to insert token: " + metricValue);
62 | ProjectName projectName = ProjectName.create(projectId);
63 | Metric metric = Metric.newBuilder()
64 | .setType(metricType)
65 | .build();
66 | TimeInterval interval = TimeInterval.newBuilder()
67 | .setEndTime(Timestamps.fromMillis(System.currentTimeMillis()))
68 | .build();
69 | TypedValue pointValue = TypedValue.newBuilder()
70 | .setInt64Value(metricValue)
71 | .build();
72 | Point point = Point.newBuilder()
73 | .setInterval(interval)
74 | .setValue(pointValue)
75 | .build();
76 | TimeSeries timeSeries = TimeSeries.newBuilder()
77 | .setMetric(metric)
78 | .setMetricKind(MetricDescriptor.MetricKind.GAUGE)
79 | .setResource(MonitoredResource.newBuilder().setType("global").build())
80 | .addPoints(point)
81 | .build();
82 | return CreateTimeSeriesRequest.newBuilder()
83 | .setNameWithProjectName(projectName)
84 | .addTimeSeries(timeSeries)
85 | .build();
86 | }
87 |
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/kubernetes/openjdk-spring-boot.yaml.in:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: openjdk-spring-boot
5 | spec:
6 | type: LoadBalancer
7 | ports:
8 | - port: 80
9 | targetPort: 8080
10 | selector:
11 | app: openjdk-spring-boot-app
12 | ---
13 | apiVersion: extensions/v1beta1
14 | kind: Deployment
15 | metadata:
16 | name: openjdk-spring-boot
17 | spec:
18 | replicas: 1
19 | template:
20 | metadata:
21 | name: openjdk-spring-boot
22 | labels:
23 | app: openjdk-spring-boot-app
24 | spec:
25 | containers:
26 | - name: openjdk-spring-boot
27 | image: ${TESTED_IMAGE}
28 | resources:
29 | requests:
30 | cpu: 100m
31 | memory: "512Mi"
32 | limits:
33 | cpu: 200m
34 | memory: "1024Mi"
35 | env:
36 | - name: HEAP_SIZE_RATIO
37 | value: "50"
38 | ports:
39 | - containerPort: 8080
40 |
--------------------------------------------------------------------------------
/java-runtimes-common/test-spring-application/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | monitoring.write.retries=3
2 | deployment.token=@deployment.token@
--------------------------------------------------------------------------------
/openjdk-common/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 | 4.0.0
21 |
22 | com.google.cloud.runtimes
23 | openjdk-parent
24 | 0.1.0-SNAPSHOT
25 | ../pom.xml
26 |
27 |
28 | Openjdk Common Docker Configuration
29 | openjdk-common
30 | pom
31 |
32 |
33 |
34 |
35 | maven-enforcer-plugin
36 |
37 |
38 |
39 | enforce
40 |
41 | validate
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-assembly-plugin
48 |
49 |
50 | package
51 |
52 | single
53 |
54 |
55 |
56 |
57 |
58 | src/main/assembly/assembly.xml
59 |
60 | gnu
61 | false
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/openjdk-common/src/main/assembly/assembly.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
20 | assembly
21 |
22 | tar.gz
23 |
24 | src/main/docker
25 | false
26 |
27 |
28 | false
29 | src/main/docker
30 |
31 |
32 | **
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/docker-entrypoint.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | is_java_cmd() {
4 | [ "$(which java)" = "$1" -o "$(readlink -f $(which java))" = "$1" ]
5 | }
6 |
7 | # Normalize invocations of "java" so that other scripts can more easily detect it
8 | if is_java_cmd "$1"; then
9 | shift
10 | set -- java "$@"
11 | # else if the first argument is not executable assume java
12 | elif ! type "$1" &>/dev/null; then
13 | set -- java "$@"
14 | fi
15 |
16 | # scan the setup-env.d directory for scripts to source for additional setup
17 | if [ -d "${SETUP_ENV:=/setup-env.d}" ]; then
18 | for SCRIPT in $( ls "${SETUP_ENV}/"[0-9]*.bash | sort ) ; do
19 | source ${SCRIPT}
20 | done
21 | fi
22 |
23 | # Normalize invocations of "java" again in case other scripts have modified it
24 | if is_java_cmd "$1"; then
25 | shift
26 | set -- java "$@"
27 | fi
28 |
29 | # Do we have JAVA_OPTS for a java command?
30 | if [ "$1" = "java" -a -n "$JAVA_OPTS" ]; then
31 | shift
32 | set -- java $JAVA_OPTS "$@"
33 | fi
34 |
35 | # configure shutdown wrapper for diagnostics if enabled
36 | source /shutdown/shutdown-env.bash
37 |
38 | # exec the entry point arguments as a command
39 | echo "Start command: $*"
40 | exec "$@"
41 |
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/setup-env.d/05-utils.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | is_true() {
4 | # case insensitive check for "true"
5 | if [[ ${1,,} = "true" ]]; then
6 | true
7 | else
8 | false
9 | fi
10 | }
11 |
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/setup-env.d/10-platform-env.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ -z "$PLATFORM" ]; then
4 | if [ -n "$GAE_INSTANCE" ]; then
5 | PLATFORM=gae
6 | else
7 | PLATFORM=unknown
8 | fi
9 | fi
10 | export PLATFORM
11 |
12 |
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/setup-env.d/25-profiler-env.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # configure Stackdriver Profiler
4 |
5 | export PROFILER_AGENT_COMMAND=${PROFILER_AGENT_COMMAND:-"-agentpath:/opt/cprof/profiler_java_agent.so=--logtostderr"}
6 |
7 | export PROFILER_AGENT=
8 |
9 | if is_true "$PROFILER_ENABLE"; then
10 | PROFILER_AGENT=${PROFILER_AGENT_COMMAND}
11 | fi
12 |
13 | # Avoid adding Profiler twice for Alpha users
14 | if [[ $JAVA_USER_OPTS = *"profiler_java_agent.so"* ]]; then
15 | echo "WARNING: Stackdriver Profiler seems to be enabled already using JAVA_USER_OPTS."
16 | PROFILER_AGENT=
17 | fi
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/setup-env.d/30-java-env.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | GetAvailableMemory () {
4 | local default_memory="$(awk '/MemTotal/{ print int($2/1024-400) }' /proc/meminfo)"
5 | local memory=""
6 |
7 | # Search for a memory limit set by kubernetes
8 | if [ -n "$KUBERNETES_MEMORY_LIMIT" ]; then
9 | memory=$((KUBERNETES_MEMORY_LIMIT / (1024 * 1024)))
10 | fi
11 |
12 | # Search for a memory limit set by cgroup
13 | local cgroup_mem_file="/sys/fs/cgroup/memory/memory.limit_in_bytes"
14 | if [ -z $memory ] && [ -r "$cgroup_mem_file" ]; then
15 | local cgroup_memory="$(cat ${cgroup_mem_file})"
16 | cgroup_memory=$((cgroup_memory / (1024 * 1024)))
17 | # Cgroup memory can be 0 or unbound, in which case we use the default limit
18 | if [ ${cgroup_memory} -gt 0 ] && [ ${cgroup_memory} -lt ${default_memory} ]; then
19 | memory=$cgroup_memory
20 | fi
21 | fi
22 |
23 | # Fallback to default memory limit
24 | if [ -z $memory ]; then
25 | memory=$default_memory
26 | fi
27 |
28 | echo $memory
29 | }
30 |
31 | # Setup default Java Options
32 | export JAVA_TMP_OPTS=${JAVA_TMP_OPTS:-$( if [[ -z ${TMPDIR} ]]; then echo ""; else echo "-Djava.io.tmpdir=$TMPDIR"; fi)}
33 | export GAE_MEMORY_MB=${GAE_MEMORY_MB:-$(GetAvailableMemory)}
34 | export HEAP_SIZE_RATIO=${HEAP_SIZE_RATIO:-"80"}
35 | export HEAP_SIZE_MB=${HEAP_SIZE_MB:-$(expr ${GAE_MEMORY_MB} \* ${HEAP_SIZE_RATIO} / 100)}
36 | export JAVA_HEAP_OPTS=${JAVA_HEAP_OPTS:-"-Xms${HEAP_SIZE_MB}M -Xmx${HEAP_SIZE_MB}M"}
37 | export JAVA_GC_OPTS=${JAVA_GC_OPTS:-"-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+PrintCommandLineFlags"}
38 | export JAVA_OPTS=${JAVA_OPTS:--showversion ${JAVA_TMP_OPTS} ${PROFILER_AGENT} ${JAVA_HEAP_OPTS} ${JAVA_GC_OPTS} ${JAVA_USER_OPTS}}
39 |
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/shutdown/shutdown-env.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /setup-env.d/05-utils.bash
4 |
5 | # If configured, output a thread dump and/or heap info on shutdown by wrapping the java process
6 | if is_true "${SHUTDOWN_LOGGING_THREAD_DUMP}" || is_true "${SHUTDOWN_LOGGING_HEAP_INFO}"; then
7 | # default shutdown logging sample threshold is 100 (100%)
8 | export SHUTDOWN_LOGGING_SAMPLE_THRESHOLD=${SHUTDOWN_LOGGING_SAMPLE_THRESHOLD:-100}
9 | random_sample=$(( RANDOM % 100 ))
10 | if (( random_sample < SHUTDOWN_LOGGING_SAMPLE_THRESHOLD)); then
11 | echo "Shutdown logging threshold of ${SHUTDOWN_LOGGING_SAMPLE_THRESHOLD}% satisfied with sample ${random_sample}."
12 | set -- /shutdown/shutdown-wrapper.bash "$@"
13 | else
14 | echo "Shutdown logging threshold of ${SHUTDOWN_LOGGING_SAMPLE_THRESHOLD}% NOT satisfied with sample ${random_sample}."
15 | fi
16 | fi
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/shutdown/shutdown-wrapper.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /setup-env.d/05-utils.bash
4 |
5 | function java_shutdown_hook {
6 | JAVA_PID=`ps -C java -o pid --no-headers`
7 | PUSER=`ps -o ruser --no-headers -p $JAVA_PID`
8 |
9 | # send thread dump to a file
10 | if is_true "${SHUTDOWN_LOGGING_THREAD_DUMP}"; then
11 | export THREAD_DUMP_FILE=${THREAD_DUMP_FILE:-/app.shutdown.threads}
12 | # run jcmd under JVM process owner and skip first 3 lines of output
13 | su $PUSER -c "jcmd $JAVA_PID Thread.print" | tail -n +3 &> $THREAD_DUMP_FILE
14 | fi
15 |
16 | # send heap info to a file
17 | if is_true "${SHUTDOWN_LOGGING_HEAP_INFO}"; then
18 | export HEAP_INFO_FILE=${HEAP_INFO_FILE:-/app.shutdown.heap}
19 | # run jcmd under JVM process owner and skip first 3 lines of output
20 | su $PUSER -c "jcmd $JAVA_PID GC.class_histogram" | tail -n +3 &> $HEAP_INFO_FILE
21 | fi
22 | }
23 |
24 | # capture the TERM signal and first generate the thread dump and/or heap info
25 | trap 'java_shutdown_hook; kill -TERM $PID' TERM
26 | "$@" &
27 | PID=$!
28 | wait $PID
29 | wait $PID
30 | if is_true "${SHUTDOWN_LOGGING_THREAD_DUMP}"; then
31 | # output thread dump to stdout
32 | echo '~~~~~~~~~~~~~~~~~~~~~~ THREAD DUMP ~~~~~~~~~~~~~~~~~~~~~~'
33 | cat $THREAD_DUMP_FILE
34 | fi
35 | if is_true "${SHUTDOWN_LOGGING_HEAP_INFO}"; then
36 | # output abbreviated heap info to stdout
37 | echo '~~~~~~~~~~~~~~~~~~~~~~~ HEAP INFO ~~~~~~~~~~~~~~~~~~~~~~~'
38 | heap_total_lines=`wc -l < "$HEAP_INFO_FILE"`
39 | HEAP_SHOW_LINES_COUNT=${HEAP_SHOW_LINES_COUNT:-54}
40 | head -"$HEAP_SHOW_LINES_COUNT" $HEAP_INFO_FILE
41 | echo "[$(( heap_total_lines - HEAP_SHOW_LINES_COUNT - 1 )) lines omitted]"
42 | tail -1 $HEAP_INFO_FILE
43 | fi
44 | exit $?
45 |
--------------------------------------------------------------------------------
/openjdk-common/src/main/docker/sid.list:
--------------------------------------------------------------------------------
1 | deb http://ftp.us.debian.org/debian sid main
2 |
--------------------------------------------------------------------------------
/openjdk-test-common/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 | 4.0.0
21 |
22 | com.google.cloud.runtimes
23 | openjdk-parent
24 | 0.1.0-SNAPSHOT
25 | ../pom.xml
26 |
27 |
28 | Openjdk Common Test resources
29 | openjdk-test-common
30 | pom
31 |
32 |
33 |
34 |
35 | org.apache.maven.plugins
36 | maven-assembly-plugin
37 |
38 |
39 | package
40 |
41 | single
42 |
43 |
44 |
45 |
46 |
47 | src/main/assembly/assembly.xml
48 |
49 | gnu
50 | false
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/main/assembly/assembly.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
20 | assembly
21 |
22 | tar.gz
23 |
24 | src/test/resources
25 | false
26 |
27 |
28 | false
29 | src/test/resources
30 |
31 |
32 | **
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/structure.yaml:
--------------------------------------------------------------------------------
1 | # Test spec for the Cloud Runtimes container structure testing framework.
2 | #
3 | # See https://github.com/GoogleCloudPlatform/runtimes-common/tree/master/functional_tests/README.md for more detail.
4 | #
5 | schemaVersion: 1.0.0
6 |
7 | commandTests:
8 | - name: 'OPENJDK_VERSION env variable is set correctly'
9 | command: ['env']
10 | expectedOutput: ['OPENJDK_VERSION=${openjdk.version}']
11 | - name: 'GAE_IMAGE_LABEL env variable is set correctly'
12 | command: ['env']
13 | expectedOutput: ['GAE_IMAGE_LABEL=${docker.tag.long}']
14 | - name: 'check entrypoint default'
15 | setup: [[ 'chmod', '+x', '/workspace/entrypoint-default.bash' ]]
16 | command: [ '/workspace/entrypoint-default.bash' ]
17 | expectedOutput: ['OK']
18 | exitCode: 0
19 | - name: 'check entrypoint args only'
20 | setup: [[ 'chmod', '+x', '/workspace/entrypoint-args-only.bash' ]]
21 | command: [ '/workspace/entrypoint-args-only.bash' ]
22 | expectedOutput: ['OK']
23 | exitCode: 0
24 | - name: 'check entrypoint setup'
25 | setup: [[ 'chmod', '+x', '/workspace/entrypoint-setup.bash' ]]
26 | command: [ '/workspace/entrypoint-setup.bash' ]
27 | expectedOutput: ['OK']
28 | exitCode: 0
29 | - name: 'check setup platform'
30 | setup: [[ 'chmod', '+x', '/workspace/setup-platform.bash' ]]
31 | command: [ '/workspace/setup-platform.bash' ]
32 | expectedOutput: ['OK']
33 | exitCode: 0
34 | - name: 'check setup java'
35 | setup: [[ 'chmod', '+x', '/workspace/setup-java.bash' ]]
36 | command: [ '/workspace/setup-java.bash' ]
37 | expectedOutput: ['OK']
38 | exitCode: 0
39 | - name: 'check setup Stackdriver Profiler'
40 | setup: [[ 'chmod', '+x', '/workspace/setup-profiler.bash' ]]
41 | command: [ '/workspace/setup-profiler.bash' ]
42 | expectedOutput: ['OK']
43 | exitCode: 0
44 | - name: 'check setup Stackdriver Profiler'
45 | setup: [[ 'chmod', '+x', '/workspace/setup-profiler.bash' ]]
46 | command: [ '/workspace/setup-profiler.bash' ]
47 | expectedOutput: ['OK']
48 | exitCode: 0
49 | - name: 'APP_DESTINATION env variable is set'
50 | command: ['env']
51 | expectedOutput: ['APP_DESTINATION=app.jar']
52 | - name: 'check shutdown logging wrapper setup'
53 | setup: [[ 'chmod', '+x', '/workspace/shutdown-env.bash' ]]
54 | command: [ '/workspace/shutdown-env.bash' ]
55 | expectedOutput: ['OK']
56 | exitCode: 0
57 | - name: 'ensure blacklisted packages are not installed as a dependency accidentally'
58 | setup: [[ 'chmod', '+x', '/workspace/test-denylisted-pkgs.bash' ]]
59 | command: [ '/workspace/test-denylisted-pkgs.bash' ]
60 | excludedOutput: ['NOT OK.* is installed']
61 | - name: 'Debian 9'
62 | command: [ 'cat', '/etc/debian_version' ]
63 | expectedOutput: ['9.*']
64 |
65 |
66 | fileExistenceTests:
67 | - name: 'ssl certificates are present'
68 | path: '/etc/ssl/certs/java/cacerts'
69 | isDirectory: false
70 | shouldExist: true
71 | - name: 'App Engine logs directory exists'
72 | path: '/var/log/app_engine'
73 | isDirectory: true
74 | shouldExist: true
75 | - name: 'Stackdriver Profiler agent is installed'
76 | path: '/opt/cprof/profiler_java_agent.so'
77 | isDirectory: false
78 | shouldExist: true
79 | - name: 'Docker entrypoint exists'
80 | path: '/docker-entrypoint.bash'
81 | isDirectory: false
82 | shouldExist: true
83 | - name: 'Env setup script dir exists'
84 | path: '/setup-env.d'
85 | isDirectory: true
86 | shouldExist: true
87 | - name: 'Utils script exists'
88 | path: '/setup-env.d/05-utils.bash'
89 | isDirectory: false
90 | shouldExist: true
91 | - name: 'Platform setup script exists'
92 | path: '/setup-env.d/10-platform-env.bash'
93 | isDirectory: false
94 | shouldExist: true
95 | - name: 'Profiler setup script exists'
96 | path: '/setup-env.d/25-profiler-env.bash'
97 | isDirectory: false
98 | shouldExist: true
99 | - name: 'Java setup script exists'
100 | path: '/setup-env.d/30-java-env.bash'
101 | isDirectory: false
102 | shouldExist: true
103 |
104 | licenseTests:
105 | - debian: true
106 | files: []
107 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/entrypoint-args-only.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set - one two three
3 | JAVA_OPTS="-java -options"
4 | sed 's/exec /# /' /docker-entrypoint.bash > /tmp/entrypoint.bash
5 | source /tmp/entrypoint.bash
6 | if [ "$(echo "$@" | xargs)" != "java -java -options one two three" ]; then
7 | echo "@='$(echo "$@" | xargs)'"
8 | else
9 | echo OK
10 | fi
11 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/entrypoint-default.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set - java one two three
3 | JAVA_OPTS="-java -options"
4 | sed 's/exec /# /' /docker-entrypoint.bash > /tmp/entrypoint.bash
5 | source /tmp/entrypoint.bash
6 | if [ "$(echo "$@" | xargs)" != "java -java -options one two three" ]; then
7 | echo "@='$(echo "$@" | xargs)'"
8 | else
9 | echo OK
10 | fi
11 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/entrypoint-setup.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -- java one two three
3 | JAVA_OPTS="-java -options"
4 |
5 | trap "rm -f /setup-env.d/01-one.bash /setup-env.d/02-two.bash /setup-env.d/03-three.bash" EXIT
6 |
7 | cat << 'EOF' > /setup-env.d/01-one.bash
8 | export ONE=OK
9 | set -- $(echo $@ | sed 's/one/1/')
10 | EOF
11 |
12 | cat << 'EOF' > /setup-env.d/02-two.bash
13 | export TWO=$ONE
14 | set -- $(echo $@ | sed 's/two/2/')
15 | EOF
16 |
17 | cat << 'EOF' > /setup-env.d/03-three.bash
18 | export THREE=$TWO
19 | set -- $(echo $@ | sed 's/three/3/')
20 | EOF
21 |
22 | sed -e 's/exec /# /' -e 's/set - /set -- /' /docker-entrypoint.bash > /tmp/entrypoint.bash
23 |
24 | source /tmp/entrypoint.bash
25 | if [ "$(echo "$@" | xargs)" != "java -java -options 1 2 3" ]; then
26 | echo "@='$(echo "$@" | xargs)'"
27 | elif [ "$THREE" != "OK" ]; then
28 | echo setup out of order $ONE, $TWO, $THREE
29 | else
30 | echo OK
31 | fi
32 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/setup-java.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function cleanEnv() {
4 | unset JAVA_OPTS TMPDIR GAE_MEMORY_MB HEAP_SIZE_MB JAVA_HEAP_OPTS JAVA_GC_OPTS JAVA_OPTS DBG_AGENT PROFILER_AGENT
5 | }
6 |
7 | cleanEnv
8 |
9 | #test default
10 | source /setup-env.d/30-java-env.bash
11 |
12 |
13 | TEST=$(echo $JAVA_OPTS | sed 's/^-showversion.*/OK/')
14 | if [ "$TEST" != "OK" ]; then
15 | echo "Show version JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
16 | exit 1
17 | fi
18 |
19 | TEST=$(echo $JAVA_OPTS | sed 's/.*-Xms.*/OK/')
20 | if [ "$TEST" != "OK" ]; then
21 | echo "No Xms JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
22 | exit 1
23 | fi
24 |
25 | TEST=$(echo $JAVA_OPTS | sed 's/.*-XX:+ParallelRefProcEnabled.*/OK/')
26 | if [ "$TEST" != "OK" ]; then
27 | echo "No XX:ParallelRefProc JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
28 | exit 1
29 | fi
30 |
31 | TEST=$(echo $JAVA_OPTS | sed 's/.*-XX:.UseG1GC.*/OK/')
32 | if [ "$TEST" != "OK" ]; then
33 | echo "No XX:UseG1GC JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
34 | exit 1
35 | fi
36 |
37 |
38 | # test base values
39 | cleanEnv
40 | TMPDIR=/var/tmp
41 | GAE_MEMORY_MB=1000
42 | source /setup-env.d/30-java-env.bash
43 | if [ "$(echo $JAVA_OPTS | xargs)" != "-showversion -Djava.io.tmpdir=/var/tmp -Xms800M -Xmx800M -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+PrintCommandLineFlags" ]; then
44 | echo "Bad values JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
45 | exit 1
46 | fi
47 |
48 | cleanEnv
49 | TMPDIR=/var/tmp
50 | GAE_MEMORY_MB=1000
51 | HEAP_SIZE_MB=500
52 | source /setup-env.d/30-java-env.bash
53 | if [ "$(echo $JAVA_OPTS | xargs)" != "-showversion -Djava.io.tmpdir=/var/tmp -Xms500M -Xmx500M -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+PrintCommandLineFlags" ]; then
54 | echo "Bad values JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
55 | exit 1
56 | fi
57 |
58 |
59 | # test direct OPTS
60 | cleanEnv
61 | TMPDIR=/var/tmp
62 | GAE_MEMORY_MB=1000
63 | HEAP_SIZE_MB=500
64 | JAVA_TMP_OPTS=-XX:Temp
65 | JAVA_HEAP_OPTS=-XX:Heap
66 | JAVA_GC_OPTS=-XX:GC
67 | PROFILER_AGENT=profiler
68 | JAVA_USER_OPTS=user
69 |
70 | source /setup-env.d/30-java-env.bash
71 | if [ "$(echo $JAVA_OPTS | xargs)" != "-showversion -XX:Temp profiler -XX:Heap -XX:GC user" ]; then
72 | echo "Bad opts JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
73 | exit 1
74 | fi
75 |
76 | #test override
77 | cleanEnv
78 | TMPDIR=/var/tmp
79 | GAE_MEMORY_MB=1000
80 | HEAP_SIZE_MB=500
81 | JAVA_TMP_OPTS=-XX:Temp
82 | JAVA_HEAP_OPTS=-XX:Heap
83 | JAVA_GC_OPTS=-XX:GC
84 | JAVA_USER_OPTS=user
85 | JAVA_OPTS=-XX:options
86 |
87 | source /setup-env.d/30-java-env.bash
88 | if [ "$(echo $JAVA_OPTS | xargs)" != "-XX:options" ]; then
89 | echo "Bad opts JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
90 | exit 1
91 | fi
92 |
93 |
94 | # test heap size ratio
95 | cleanEnv
96 | GAE_MEMORY_MB=1000
97 | HEAP_SIZE_RATIO=50
98 | source /setup-env.d/30-java-env.bash
99 |
100 | TEST_MIN_HEAP=$(echo $JAVA_OPTS | sed 's/.*-Xms500M .*/OK/')
101 | TEST_MAX_HEAP=$(echo $JAVA_OPTS | sed 's/.*-Xmx500M .*/OK/')
102 |
103 | if [ "$TEST_MIN_HEAP" != "OK" -o "$TEST_MAX_HEAP" != "OK" ]; then
104 | echo "Bad values JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
105 | exit 1
106 | fi
107 |
108 |
109 | #test GKE environment
110 | cleanEnv
111 | TMPDIR=/var/tmp
112 | KUBERNETES_MEMORY_LIMIT=20000000
113 | HEAP_SIZE_RATIO=30
114 | source /setup-env.d/30-java-env.bash
115 |
116 | TEST_MIN_HEAP=$(echo $JAVA_OPTS | sed 's/.*-Xms5M .*/OK/')
117 | TEST_MAX_HEAP=$(echo $JAVA_OPTS | sed 's/.*-Xmx5M .*/OK/')
118 |
119 | if [ "$TEST_MIN_HEAP" != "OK" -o "$TEST_MAX_HEAP" != "OK" ]; then
120 | echo "Memory limit set by kubernetes is not considered in JAVA_OPTS='$(echo $JAVA_OPTS | xargs)'"
121 | exit 1
122 | fi
123 |
124 | echo OK
125 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/setup-platform.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #test default
4 | unset PLATFORM GAE_INSTANCE
5 | source /setup-env.d/10-platform-env.bash
6 | if [ "$PLATFORM" != "unknown" ]; then
7 | echo "Bad default PLATFORM='$PLATFORM'"
8 | exit 1
9 | fi
10 |
11 | #test GAE
12 | unset PLATFORM GAE_INSTANCE
13 | GAE_INSTANCE=12345
14 | source /setup-env.d/10-platform-env.bash
15 | if [ "$PLATFORM" != "gae" ]; then
16 | echo "Bad gae PLATFORM='$PLATFORM'"
17 | exit 1
18 | fi
19 |
20 | #test forced
21 | unset PLATFORM GAE_INSTANCE
22 | GAE_INSTANCE=12345
23 | PLATFORM=special
24 | source /setup-env.d/10-platform-env.bash
25 | if [ "$PLATFORM" != "special" ]; then
26 | echo "Bad forced PLATFORM='$PLATFORM'"
27 | exit 1
28 | fi
29 |
30 |
31 | echo OK
32 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/setup-profiler.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /setup-env.d/05-utils.bash
4 |
5 | function testProfilerOn() {
6 | source /setup-env.d/25-profiler-env.bash
7 | if [ "$PROFILER_AGENT" != "-agentpath:/opt/cprof/profiler_java_agent.so=--logtostderr" ]; then
8 | echo "Profiler should be ON because $1"
9 | exit 1
10 | fi
11 | }
12 |
13 | function testProfilerOff() {
14 | source /setup-env.d/25-profiler-env.bash
15 | if [ "$PROFILER_AGENT" != "" ]; then
16 | echo "Profiler should be OFF because $1"
17 | exit 1
18 | fi
19 | }
20 |
21 | function cleanEnv() {
22 | unset PROFILER_AGENT
23 | unset PROFILER_ENABLE
24 | unset PLATFORM
25 | unset JAVA_USER_OPTS
26 | }
27 |
28 | # test default - profiler OFF
29 | cleanEnv
30 | testProfilerOff "that's the default"
31 |
32 | # test GAE default - profiler OFF
33 | cleanEnv
34 | PLATFORM=gae
35 | testProfilerOff "that's the default on GAE"
36 |
37 | # test GKE default - profiler OFF
38 | cleanEnv
39 | PLATFORM=gke
40 | testProfilerOff "that's the default on GKE"
41 |
42 | # test PROFILER_ENABLE = true
43 | cleanEnv
44 | PROFILER_ENABLE=true
45 | testProfilerOn "PROFILER_ENABLE=$PROFILER_ENABLE"
46 |
47 | # test PROFILER_ENABLE = True
48 | cleanEnv
49 | PROFILER_ENABLE=True
50 | testProfilerOn "PROFILER_ENABLE=$PROFILER_ENABLE"
51 |
52 | # test PROFILER_ENABLE = false
53 | cleanEnv
54 | PROFILER_ENABLE=false
55 | testProfilerOff "PROFILER_ENABLE=$PROFILER_ENABLE"
56 |
57 | # test PROFILER_ENABLE = False
58 | cleanEnv
59 | PROFILER_ENABLE=False
60 | testProfilerOff "PROFILER_ENABLE=$PROFILER_ENABLE"
61 |
62 | # test JAVA_USER_OPTS = -agentpath:/opt/cprof/profiler_java_agent.so=--logtostderr
63 | cleanEnv
64 | JAVA_USER_OPTS=-agentpath:/opt/cprof/profiler_java_agent.so=--logtostderr
65 | PROFILER_ENABLE=True
66 | testProfilerOff "JAVA_USER_OPTS=$JAVA_USER_OPTS"
67 |
68 | echo OK
69 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/shutdown-env.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | wrapper="/shutdown/shutdown-wrapper.bash"
4 |
5 | function doTest() {
6 | test_setup="testing SHUTDOWN_LOGGING_THREAD_DUMP=$SHUTDOWN_LOGGING_THREAD_DUMP, " \
7 | "SHUTDOWN_LOGGING_HEAP_INFO=$SHUTDOWN_LOGGING_HEAP_INFO, " \
8 | "SHUTDOWN_LOGGING_SAMPLE_THRESHOLD=$SHUTDOWN_LOGGING_SAMPLE_THRESHOLD."
9 | expected=$1
10 | set - java
11 | JAVA_OPTS=" "
12 | source /shutdown/shutdown-env.bash > /dev/null
13 | if [ "$(echo "$@" | xargs)" != "$expected" ]; then
14 | echo $test_setup
15 | echo "command='$(echo "$@" | xargs)' rather than expected '$expected'"
16 | echo FAILED
17 | exit 1
18 | fi
19 | }
20 |
21 | function cleanEnv() {
22 | unset SHUTDOWN_LOGGING_THREAD_DUMP
23 | unset SHUTDOWN_LOGGING_HEAP_INFO
24 | unset SHUTDOWN_LOGGING_SAMPLE_THRESHOLD
25 | }
26 |
27 | # default - no shutdown wrapper
28 | cleanEnv
29 | doTest "java"
30 |
31 | # thread dump on
32 | cleanEnv
33 | SHUTDOWN_LOGGING_THREAD_DUMP=True
34 | doTest "$wrapper java"
35 |
36 | # heap info on
37 | cleanEnv
38 | SHUTDOWN_LOGGING_HEAP_INFO=True
39 | doTest "$wrapper java"
40 |
41 | # thread dump and heap info off
42 | cleanEnv
43 | SHUTDOWN_LOGGING_THREAD_DUMP=False
44 | SHUTDOWN_LOGGING_HEAP_INFO=False
45 | doTest "java"
46 |
47 | # both on
48 | cleanEnv
49 | SHUTDOWN_LOGGING_THREAD_DUMP=True
50 | SHUTDOWN_LOGGING_HEAP_INFO=True
51 | doTest "$wrapper java"
52 |
53 | # both on but threshold 0
54 | cleanEnv
55 | SHUTDOWN_LOGGING_THREAD_DUMP=True
56 | SHUTDOWN_LOGGING_HEAP_INFO=True
57 | SHUTDOWN_LOGGING_SAMPLE_THRESHOLD=0
58 | doTest "java"
59 |
60 | # both on but threshold 100
61 | cleanEnv
62 | SHUTDOWN_LOGGING_THREAD_DUMP=True
63 | SHUTDOWN_LOGGING_HEAP_INFO=True
64 | SHUTDOWN_LOGGING_SAMPLE_THRESHOLD=100
65 | doTest "$wrapper java"
66 |
67 | echo OK
68 |
--------------------------------------------------------------------------------
/openjdk-test-common/src/test/resources/workspace/test-denylisted-pkgs.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | DENYLIST="\
4 | jvm-7-avian-jre \
5 | java7-runtime-headless \
6 | python2.7-pyjavaproperties \
7 | libjsr107cache-java \
8 | libbiojava1.7-java \
9 | oracle-java7-installer \
10 | oracle-java7-jdk \
11 | openjdk-7-jre-zero \
12 | sun-java7-jre \
13 | java7-sdk \
14 | libdb4.7-java-dev \
15 | openjdk-7-jdk \
16 | java7-sdk-headless \
17 | openjdk-7-jre-headless \
18 | java7-runtime \
19 | libtomcat7-java \
20 | openjdk-7-dbg \
21 | openjdk-7-jre-dcevm \
22 | openjdk-7-jre-lib \
23 | uwsgi-plugin-jvm-openjdk-7 \
24 | openjdk-7-jre \
25 | openjdk-7-source \
26 | icedtea-7-jre-jamvm \
27 | openjdk-7-demo \
28 | openjdk-7-doc \
29 | libnb-platform7-devel-java \
30 | uwsgi-plugin-jwsgi-openjdk-7"
31 |
32 |
33 | for PKG in $DENYLIST;
34 | do
35 | dpkg -l | grep '^.i' | grep $PKG > /dev/null && echo "NOT OK. $PKG is installed" || echo "OK. $PKG is not installed"
36 | done
37 |
--------------------------------------------------------------------------------
/openjdk11/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 | 4.0.0
21 |
22 | com.google.cloud.runtimes
23 | openjdk-parent
24 | 0.1.0-SNAPSHOT
25 | ../pom.xml
26 |
27 | Google App Engine Image for OpenJDK (openjdk11)
28 | openjdk11
29 | pom
30 |
31 |
32 | 11
33 |
34 | ${openjdk.version.major}${openjdk.version.minor}
35 | gcr.io/google-appengine/debian9
36 | ${docker.image.baseName}:${docker.tag.long}
37 |
38 |
39 |
40 |
41 | com.google.cloud.runtimes
42 | openjdk-common
43 | ${project.version}
44 | tar.gz
45 |
46 |
47 | com.google.cloud.runtimes
48 | openjdk-test-common
49 | ${project.version}
50 | tar.gz
51 |
52 |
53 | com.google.cloud.runtimes
54 | test-spring-application
55 | 1.0.0
56 |
57 |
58 |
59 |
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-dependency-plugin
64 |
65 |
66 | unpack-openjdk-common
67 | generate-resources
68 |
69 |
70 | unpack-openjdk-test-common
71 | generate-test-resources
72 |
73 |
74 |
75 |
76 |
77 | io.fabric8
78 | docker-maven-plugin
79 |
80 |
81 | docker-build
82 | package
83 |
84 |
85 |
86 |
87 |
88 | org.codehaus.mojo
89 | exec-maven-plugin
90 |
91 |
92 | common-structure-test
93 | integration-test
94 |
95 |
96 | local-shutdown-test
97 | integration-test
98 |
99 |
100 |
101 | openjdk11-structure-test
102 | integration-test
103 |
104 | exec
105 |
106 |
107 | ${project.parent.basedir}/scripts/structure_test.sh
108 | ${project.basedir}
109 |
110 | ${docker.image.name}
111 | ${project.build.testOutputDirectory}
112 | ${project.build.testOutputDirectory}/openjdk11-structure.yaml
113 |
114 |
115 |
116 |
117 |
118 |
119 | maven-resources-plugin
120 |
121 |
122 | generate-test-resources
123 | generate-test-resources
124 |
125 | testResources
126 |
127 |
128 | ${project.build.testOutputDirectory}
129 |
130 |
131 | ${basedir}/src/test/resources
132 | true
133 |
134 | **
135 |
136 |
137 |
138 |
139 |
140 |
141 | copy-resources
142 | generate-resources
143 |
144 | copy-resources
145 |
146 |
147 | ${docker.staging.dir}
148 |
149 |
150 | ${basedir}/src/main/docker
151 | true
152 |
153 | **
154 |
155 |
156 |
157 |
158 |
159 |
160 | filter-test-resources
161 | process-test-resources
162 |
163 | copy-resources
164 |
165 |
166 | ${project.build.testOutputDirectory}/openjdk-test-common-out
167 |
168 |
169 | ${project.build.testOutputDirectory}/openjdk-test-common
170 | true
171 |
172 | **
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/openjdk11/src/main/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2014 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | FROM ${docker.appengine.image}
16 | ENV DEBIAN_FRONTEND noninteractive
17 |
18 | # Create env vars to identify image
19 | ENV OPENJDK_VERSION ${openjdk.version}
20 | ENV GAE_IMAGE_NAME ${project.artifactId}
21 | ENV GAE_IMAGE_LABEL ${docker.tag.long}
22 |
23 | RUN \
24 | # add debian stretch-backports repo in order to install openjdk11
25 | echo 'deb http://httpredir.debian.org/debian stretch-backports main' > /etc/apt/sources.list.d/stretch-backports.list \
26 |
27 | && apt-get -q update \
28 | && apt-get -y -q --no-install-recommends install \
29 | # install the jdk and its dependencies
30 | ca-certificates-java \
31 | openjdk-${openjdk.version.major}-jdk-headless=${openjdk.version}'*' \
32 | # procps is used in the jvm shutdown hook
33 | procps \
34 | # other system utilities
35 | netbase \
36 | unzip \
37 | wget \
38 |
39 | # cleanup package manager caches
40 | && apt-get clean \
41 | && rm /var/lib/apt/lists/*_*
42 |
43 | # Add the Stackdriver Profiler libraries
44 | ADD https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz /opt/cprof/
45 | COPY docker-entrypoint.bash /
46 | COPY setup-env.d /setup-env.d/
47 | COPY shutdown/ /shutdown/
48 | RUN tar Cxfvz /opt/cprof /opt/cprof/profiler_java_agent.tar.gz --no-same-owner \
49 | && rm /opt/cprof/profiler_java_agent.tar.gz \
50 | && chmod +x /docker-entrypoint.bash /shutdown/*.bash /setup-env.d/*.bash \
51 | && mkdir /var/log/app_engine \
52 | && chmod go+rwx /var/log/app_engine
53 |
54 | ENV APP_DESTINATION ${docker.application.destination}
55 |
56 | ENTRYPOINT ["/docker-entrypoint.bash"]
57 | CMD ["java", "-jar", "${docker.application.destination}"]
58 |
--------------------------------------------------------------------------------
/openjdk11/src/test/resources/jdk11-compilation-test/.gitignore:
--------------------------------------------------------------------------------
1 | out/
--------------------------------------------------------------------------------
/openjdk11/src/test/resources/jdk11-compilation-test/com.google.greetings/com/google/greetings/Main.java:
--------------------------------------------------------------------------------
1 | package com.google.greetings;
2 | import com.google.world.World;
3 |
4 | public class Main {
5 | public static void main(String[] args) {
6 | System.out.format("Greetings %s!%n", World.name());
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/openjdk11/src/test/resources/jdk11-compilation-test/com.google.greetings/module-info.java:
--------------------------------------------------------------------------------
1 | module com.google.greetings {
2 | exports com.google.greetings;
3 | requires com.google.world;
4 | }
--------------------------------------------------------------------------------
/openjdk11/src/test/resources/jdk11-compilation-test/com.google.world/com/google/world/World.java:
--------------------------------------------------------------------------------
1 | package com.google.world;
2 |
3 | public class World {
4 | public static String name() {
5 | return "world";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/openjdk11/src/test/resources/jdk11-compilation-test/com.google.world/module-info.java:
--------------------------------------------------------------------------------
1 | module com.google.world {
2 | exports com.google.world;
3 | }
--------------------------------------------------------------------------------
/openjdk11/src/test/resources/jdk11-compilation-test/compile-and-run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | SOURCE_DIR=$1
4 |
5 | if [ -z $SOURCE_DIR ]; then
6 | echo "USAGE: $0 "
7 | exit 1;
8 | fi
9 |
10 | # compile modules
11 | javac -d out --module-source-path $SOURCE_DIR $(find $SOURCE_DIR -name '*.java')
12 |
13 | # run main class
14 | java --module-path out -m com.google.greetings/com.google.greetings.Main
15 |
--------------------------------------------------------------------------------
/openjdk11/src/test/resources/openjdk11-structure.yaml:
--------------------------------------------------------------------------------
1 | # Test spec for the Cloud Runtimes container structure testing framework.
2 | #
3 | # See https://github.com/GoogleCloudPlatform/runtimes-common/tree/master/functional_tests/README.md for more detail.
4 | #
5 | schemaVersion: 1.0.0
6 |
7 | commandTests:
8 | - name: 'correct java version is installed'
9 | command: ['java', '-version']
10 | expectedError: ['openjdk version "${openjdk.version.major}']
11 | - name: 'correct javac version is installed'
12 | command: ['javac', '-version']
13 | expectedOut: ['javac ${openjdk.version.major}']
14 | - name: 'compilation of openjdk11 code works'
15 | setup: [['chmod', '+x', '/workspace/jdk11-compilation-test/compile-and-run.sh']]
16 | command: ['/workspace/jdk11-compilation-test/compile-and-run.sh', '/workspace/jdk11-compilation-test']
17 | expectedOut: ['Greetings World!']
18 |
--------------------------------------------------------------------------------
/openjdk8/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 | 4.0.0
21 |
22 | com.google.cloud.runtimes
23 | openjdk-parent
24 | 0.1.0-SNAPSHOT
25 | ../pom.xml
26 |
27 | Google App Engine Image for OpenJDK (openjdk8)
28 | openjdk8
29 | pom
30 |
31 |
32 | 8
33 |
34 | ${openjdk.version.major}${openjdk.version.minor}
35 | gcr.io/google-appengine/debian9
36 | ${docker.image.baseName}:${docker.tag.long}
37 |
38 |
39 |
40 |
41 | com.google.cloud.runtimes
42 | openjdk-common
43 | ${project.version}
44 | tar.gz
45 |
46 |
47 | com.google.cloud.runtimes
48 | openjdk-test-common
49 | ${project.version}
50 | tar.gz
51 |
52 |
53 | com.google.cloud.runtimes
54 | test-spring-application
55 | 1.0.0
56 |
57 |
58 |
59 |
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-dependency-plugin
64 |
65 |
66 | unpack-openjdk-common
67 | generate-resources
68 |
69 |
70 | unpack-openjdk-test-common
71 | generate-test-resources
72 |
73 |
74 |
75 |
76 |
77 | io.fabric8
78 | docker-maven-plugin
79 |
80 |
81 | docker-build
82 | package
83 |
84 |
85 |
86 |
87 |
88 | org.codehaus.mojo
89 | exec-maven-plugin
90 |
91 |
92 |
93 | common-structure-test
94 | integration-test
95 |
96 |
97 | local-shutdown-test
98 | integration-test
99 |
100 |
101 |
102 | openjdk8-structure-test
103 | integration-test
104 |
105 | exec
106 |
107 |
108 | ${project.parent.basedir}/scripts/structure_test.sh
109 | ${project.basedir}
110 |
111 | ${docker.image.name}
112 | ${project.build.testOutputDirectory}
113 | ${project.build.testOutputDirectory}/openjdk8-structure.yaml
114 |
115 |
116 |
117 |
118 |
119 |
120 | maven-resources-plugin
121 |
122 |
123 | generate-test-resources
124 | generate-test-resources
125 |
126 | testResources
127 |
128 |
129 | ${project.build.testOutputDirectory}
130 |
131 |
132 | ${basedir}/src/test/resources
133 | true
134 |
135 | **
136 |
137 |
138 |
139 |
140 |
141 |
142 | copy-resources
143 | generate-resources
144 |
145 | copy-resources
146 |
147 |
148 | ${docker.staging.dir}
149 |
150 |
151 | ${basedir}/src/main/docker
152 | true
153 |
154 | **
155 |
156 |
157 |
158 |
159 |
160 |
161 | filter-test-resources
162 | process-test-resources
163 |
164 | copy-resources
165 |
166 |
167 | ${project.build.testOutputDirectory}/openjdk-test-common-out
168 |
169 |
170 | ${project.build.testOutputDirectory}/openjdk-test-common
171 | true
172 |
173 | **
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/openjdk8/src/main/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2014 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | FROM ${docker.appengine.image}
16 | ENV DEBIAN_FRONTEND noninteractive
17 |
18 | # Create env vars to identify image
19 | ENV OPENJDK_VERSION ${openjdk.version}
20 | ENV GAE_IMAGE_NAME ${project.artifactId}
21 | ENV GAE_IMAGE_LABEL ${docker.tag.long}
22 |
23 | RUN echo 'deb http://archive.debian.org/debian stretch main' > /etc/apt/sources.list \
24 | && apt-get -q update \
25 | && apt-get -y -q --no-install-recommends install \
26 | # install the jdk and its dependencies
27 | ca-certificates-java \
28 | # procps is used in the jvm shutdown hook
29 | procps \
30 | # other system utilities
31 | netbase \
32 | wget \
33 | unzip \
34 | fontconfig \
35 | locales \
36 |
37 | # cleanup package manager caches
38 | && apt-get clean \
39 | && rm /var/lib/apt/lists/*_*
40 |
41 | ARG OPENJDK_VER='jdk8u345-b01'
42 | ARG OPENJDK_VER_NAME='8u345b01'
43 | ARG OPENJDK_TEMP_PATH='/tmp/openjdk'
44 | ARG OPENJDK_OUT='/usr/lib/openjdk'
45 | ENV PATH $OPENJDK_OUT/bin:$PATH
46 | ENV JAVA_HOME $OPENJDK_OUT
47 |
48 | RUN mkdir -p $OPENJDK_TEMP_PATH \
49 | && mkdir -p $OPENJDK_OUT \
50 | && wget -O $OPENJDK_TEMP_PATH/openjdk.tar.gz https://github.com/adoptium/temurin8-binaries/releases/download/$OPENJDK_VER/OpenJDK8U-jdk_x64_linux_hotspot_$OPENJDK_VER_NAME.tar.gz \
51 | && tar Cxfvz --file $OPENJDK_TEMP_PATH/openjdk.tar.gz --directory $OPENJDK_TEMP_PATH --no-same-owner \
52 | && rm $OPENJDK_TEMP_PATH/openjdk.tar.gz \
53 | && cp -r $OPENJDK_TEMP_PATH/$OPENJDK_VER/* $OPENJDK_OUT \
54 | && rm -rf $OPENJDK_TEMP_PATH \
55 | && ln -s $OPENJDK_OUT/bin/* /usr/local/bin/
56 |
57 | # Add the Stackdriver Profiler libraries
58 | ADD https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz /opt/cprof/
59 | COPY docker-entrypoint.bash /
60 | COPY setup-env.d /setup-env.d/
61 | COPY shutdown/ /shutdown/
62 | RUN tar Cxfvz /opt/cprof /opt/cprof/profiler_java_agent.tar.gz --no-same-owner \
63 | && rm /opt/cprof/profiler_java_agent.tar.gz \
64 | && chmod +x /docker-entrypoint.bash /shutdown/*.bash /setup-env.d/*.bash \
65 | && mkdir /var/log/app_engine \
66 | && chmod go+rwx /var/log/app_engine
67 |
68 | ENV APP_DESTINATION ${docker.application.destination}
69 |
70 | ENTRYPOINT ["/docker-entrypoint.bash"]
71 | CMD ["java", "-jar", "${docker.application.destination}"]
72 |
--------------------------------------------------------------------------------
/openjdk8/src/test/resources/openjdk8-structure.yaml:
--------------------------------------------------------------------------------
1 | # Test spec for the Cloud Runtimes container structure testing framework.
2 | #
3 | # See https://github.com/GoogleCloudPlatform/runtimes-common/tree/master/functional_tests/README.md for more detail.
4 | #
5 | schemaVersion: 1.0.0
6 |
7 | commandTests:
8 | - name: 'correct java version is installed'
9 | command: ['java', '-version']
10 | expectedError: ['openjdk version "1\.${openjdk.version.major}.*${openjdk.version.minor}"']
11 | - name: 'correct javac version is installed'
12 | command: ['javac', '-version']
13 | expectedError: ['javac 1\.${openjdk.version.major}.*${openjdk.version.minor}']
14 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 | 4.0.0
18 |
19 | com.google.cloud.runtimes
20 | openjdk-parent
21 | 0.1.0-SNAPSHOT
22 | pom
23 | Google App Engine OpenJDK Runtime Parent
24 |
25 |
26 | UTF-8
27 | UTF-8
28 | yyyy-MM-dd-HH-mm
29 | ${openjdk.version.major}
30 | ${openjdk.version.major}-${maven.build.timestamp}
31 | openjdk
32 | app.jar
33 | ${project.build.outputDirectory}/docker
34 |
35 |
36 |
37 |
38 | Apache License 2.0
39 | http://www.apache.org/licenses/LICENSE-2.0.html
40 | repo
41 |
42 |
43 |
44 |
45 | openjdk-common
46 | openjdk-test-common
47 | openjdk8
48 | openjdk11
49 | java-runtimes-common/test-spring-application
50 |
51 |
52 |
53 |
54 |
55 | junit
56 | junit
57 | 4.12
58 | test
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | org.apache.maven.plugins
68 | maven-enforcer-plugin
69 | 1.4.1
70 |
71 |
72 |
73 | [3.3,)
74 |
75 |
76 | [1.8,)
77 |
78 |
79 |
80 |
81 |
82 |
83 | io.fabric8
84 | docker-maven-plugin
85 | 0.21.0
86 |
87 | true
88 | always
89 |
90 |
91 | ${docker.image.name}
92 |
93 | ${docker.staging.dir}
94 | true
95 |
96 | ${docker.tag.short}
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | docker-build
105 | none
106 |
107 | build
108 |
109 |
110 |
111 |
112 |
113 |
114 | org.apache.maven.plugins
115 | maven-dependency-plugin
116 | 2.10
117 |
118 |
119 |
120 | unpack-openjdk-common
121 | none
122 |
123 | unpack
124 |
125 |
126 |
127 |
128 | com.google.cloud.runtimes
129 | openjdk-common
130 | ${project.version}
131 | tar.gz
132 | true
133 | ${docker.staging.dir}
134 |
135 |
136 |
137 |
138 |
139 | unpack-openjdk-test-common
140 | none
141 |
142 | unpack
143 |
144 |
145 |
146 |
147 | com.google.cloud.runtimes
148 | openjdk-test-common
149 | ${project.version}
150 | tar.gz
151 | true
152 | ${project.build.testOutputDirectory}/openjdk-test-common
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | org.codehaus.mojo
162 | exec-maven-plugin
163 | 1.4.0
164 |
165 |
166 | common-structure-test
167 |
169 | none
170 |
171 | exec
172 |
173 |
174 | ${project.parent.basedir}/scripts/structure_test.sh
175 | ${project.build.outputDirectory}
176 |
177 | ${docker.image.name}
178 | ${project.build.testOutputDirectory}/openjdk-test-common-out/workspace
179 | ${project.build.testOutputDirectory}/openjdk-test-common-out/structure.yaml
180 |
181 |
182 |
183 |
184 | local-shutdown-test
185 |
187 | none
188 |
189 | exec
190 |
191 |
192 | ${project.parent.basedir}/scripts/local_shutdown_test.sh
193 | ${project.build.outputDirectory}
194 |
195 | ${docker.image.name}
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | org.apache.maven.plugins
204 | maven-compiler-plugin
205 | 3.2
206 |
207 | 1.8
208 | 1.8
209 |
210 |
211 |
212 |
213 | org.apache.maven.plugins
214 | maven-resources-plugin
215 | 3.0.1
216 |
217 |
218 |
219 | org.apache.maven.plugins
220 | maven-surefire-plugin
221 | 2.18
222 |
223 | false
224 |
225 |
226 |
227 |
228 | org.apache.maven.plugins
229 | maven-install-plugin
230 | 2.5.2
231 |
232 |
233 |
234 | org.apache.maven.plugins
235 | maven-jar-plugin
236 | 2.5
237 |
238 |
239 |
240 | org.apache.maven.plugins
241 | maven-antrun-plugin
242 | 1.8
243 |
244 |
245 |
246 | org.apache.maven.plugins
247 | maven-deploy-plugin
248 | 2.8.2
249 |
250 |
251 |
252 |
253 |
254 |
255 | org.apache.maven.plugins
256 | maven-checkstyle-plugin
257 | 2.17
258 | true
259 |
260 |
261 | com.puppycrawl.tools
262 | checkstyle
263 | 8.1
264 |
265 |
266 |
267 |
268 | checkstyle
269 | validate
270 |
271 | check
272 |
273 |
274 | google_checks.xml
275 | checkstyle/checkstyle-suppressions.xml
276 | true
277 | true
278 | error
279 | true
280 | true
281 |
282 |
283 |
284 |
285 |
286 | org.apache.maven.plugins
287 | maven-failsafe-plugin
288 | 2.19.1
289 |
290 | false
291 |
292 |
293 |
294 |
295 | integration-test
296 | verify
297 |
298 |
299 |
300 |
301 |
302 | org.apache.maven.surefire
303 | surefire-junit47
304 | 2.19.1
305 |
306 |
307 |
308 |
309 | org.codehaus.mojo
310 | properties-maven-plugin
311 | 1.0.0
312 |
313 |
314 | build-properties
315 |
316 | write-project-properties
317 |
318 |
319 |
320 | ${project.build.directory}/build.properties
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
--------------------------------------------------------------------------------
/scripts/ae_integration_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2016 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -e
18 |
19 | # Runs integration tests on a given runtime image
20 |
21 | readonly dir=`dirname $0`
22 | readonly projectRoot=$dir/..
23 | readonly testAppDir=$projectRoot/java-runtimes-common/test-spring-application
24 | readonly deployDir=$testAppDir/target/deploy
25 | readonly DEPLOYMENT_TOKEN=$(date -u +%Y-%m-%d-%H-%M-%S-%N)
26 |
27 | readonly imageUnderTest=$1
28 | if [ -z "${imageUnderTest}" ]; then
29 | echo "Usage: ${0} [gae_deployment_version]"
30 | exit 1
31 | fi
32 |
33 | # If provided, pin to a specific version. Otherwise, generate a random new version ID to prevent
34 | # inadvertent collisions.
35 | gaeDeploymentVersion=$2
36 | if [ -z "${gaeDeploymentVersion}" ]; then
37 | gaeDeploymentVersion=$(date -u +%Y-%m-%d-%H-%M-%S-%N)
38 | readonly tearDown="true"
39 | fi
40 | DEPLOYMENT_OPTS="-v $gaeDeploymentVersion --no-promote --no-stop-previous-version"
41 | DEPLOYMENT_VERSION_URL_PREFIX="$gaeDeploymentVersion-dot-"
42 |
43 | # build the test app
44 | pushd $testAppDir
45 | mvn clean install -Pruntime.custom -Dapp.deploy.image=$imageUnderTest -Ddeployment.token="${DEPLOYMENT_TOKEN}" -DskipTests --batch-mode
46 | popd
47 |
48 | # deploy to app engine
49 | pushd $deployDir
50 | echo "Deploying to App Engine: gcloud app deploy -q ${DEPLOYMENT_OPTS}"
51 | gcloud app deploy -q ${DEPLOYMENT_OPTS}
52 | popd
53 |
54 | DEPLOYED_APP_URL="http://${DEPLOYMENT_VERSION_URL_PREFIX}$(gcloud app describe | grep defaultHostname | awk '{print $2}')"
55 |
56 | echo "App deployed to URL: $DEPLOYED_APP_URL, making sure it accepts connections..."
57 | # sometimes AppEngine deploys, returns the URL and then serves 502 errors, this was introduced to wait for that to be resolved
58 | until [[ $(curl --silent --fail "$DEPLOYED_APP_URL/deployment.token" | grep "$DEPLOYMENT_TOKEN") ]]; do
59 | sleep 2
60 | done
61 |
62 |
63 | echo "Success pinging app! Output: "
64 | echo "-----"
65 | curl -s "${DEPLOYED_APP_URL}"
66 | echo ""
67 | echo "Deployment token: $DEPLOYMENT_TOKEN"
68 | echo "-----"
69 |
70 | echo "Running integration tests on application that is deployed at $DEPLOYED_APP_URL"
71 |
72 | # run in cloud container builder
73 | gcloud builds submit \
74 | --config $dir/integration_test.yaml \
75 | --substitutions "_DEPLOYED_APP_URL=$DEPLOYED_APP_URL" \
76 | $dir
77 |
78 | if [ "$tearDown" == "true" ]; then
79 | # run a cleanup build once tests have finished executing
80 | gcloud builds submit \
81 | --config $dir/integration_test_cleanup.yaml \
82 | --substitutions "_VERSION=$gaeDeploymentVersion" \
83 | --async \
84 | --no-source
85 | fi
86 |
87 |
--------------------------------------------------------------------------------
/scripts/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2016 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -e
18 |
19 | usage() {
20 | echo "Usage: ${0} "
21 | echo " where include:"
22 | echo " -p|--publishing-project - GCP project to use for publishing. Used to generate the destination docker repository name in gcr.io"
23 | echo " -m|--module - one of {openjdk8, openjdk11}"
24 | echo " [ -t|--tag-suffix ] - suffix for the tag that is applied to the built image"
25 | echo " [ -s|--staging-project ] - GCP project to use for staging images. If not provided, the publishing project will be used."
26 | echo " [ -l|--local ] - runs the build locally"
27 | exit 1
28 | }
29 |
30 | # Parse arguments to this script
31 | while [[ $# -gt 0 ]]; do
32 | key="$1"
33 | case $key in
34 | -p|--publishing-project)
35 | PUBLISHING_PROJECT="$2"
36 | shift # past argument
37 | ;;
38 | -m|--module)
39 | MODULE="$2"
40 | shift # past argument
41 | ;;
42 | -t|--tag-suffix)
43 | TAG_SUFFIX="$2"
44 | shift # past argument
45 | ;;
46 | -s|--staging-project)
47 | STAGING_PROJECT="$2"
48 | shift # past argument
49 | ;;
50 | -l|--local)
51 | LOCAL_BUILD="true"
52 | ;;
53 | *)
54 | # unknown option
55 | usage
56 | ;;
57 | esac
58 | shift
59 | done
60 |
61 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
62 | PROJECT_ROOT=$DIR/..
63 | RUNTIME_NAME="openjdk"
64 |
65 | if [ -z "${PUBLISHING_PROJECT}" -o -z "${MODULE}" ]; then
66 | usage
67 | fi
68 |
69 | if [ "${MODULE}" == "openjdk8" ]; then
70 | TAG_PREFIX="8"
71 | elif [ "${MODULE}" == "openjdk11" ]; then
72 | TAG_PREFIX="11"
73 | else
74 | echo "${MODULE} is not a supported module"
75 | usage
76 | fi
77 |
78 | if [ -z "$TAG_SUFFIX" ]; then
79 | TAG_SUFFIX="$(date -u +%Y-%m-%d_%H_%M)"
80 | fi
81 |
82 | if [ -z "${STAGING_PROJECT}" ]; then
83 | STAGING_PROJECT=$PUBLISHING_PROJECT
84 | fi
85 |
86 | # export TAG, IMAGE for use in downstream scripts
87 | export TAG="${TAG_PREFIX}-${TAG_SUFFIX}"
88 | export IMAGE="gcr.io/${PUBLISHING_PROJECT}/${RUNTIME_NAME}:${TAG}"
89 | echo "IMAGE: $IMAGE"
90 |
91 | STAGING_IMAGE="gcr.io/${STAGING_PROJECT}/${RUNTIME_NAME}_staging:${TAG}"
92 |
93 | # build and test the runtime image
94 | BUILD_FLAGS="--config $PROJECT_ROOT/cloudbuild.yaml"
95 | BUILD_FLAGS="$BUILD_FLAGS --substitutions _IMAGE=$IMAGE,_MODULE=$MODULE" # temporarily getting rid of this ,_STAGING_IMAGE=$STAGING_IMAGE"
96 | BUILD_FLAGS="$BUILD_FLAGS $PROJECT_ROOT"
97 |
98 | if [ "${LOCAL_BUILD}" = "true" ]; then
99 | if [ ! $(which cloud-build-local) ]; then
100 | echo "The cloud-build-local tool is required to perform a local build. To install it, run 'gcloud components install cloud-build-local'"
101 | exit 1
102 | fi
103 | cloud-build-local --dryrun=false $BUILD_FLAGS
104 | else
105 | gcloud builds submit --timeout=25m $BUILD_FLAGS
106 | fi
107 |
108 |
--------------------------------------------------------------------------------
/scripts/ci-build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2016 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Build script for CI-like environments. Sets up local dependencies required for performing a
18 | # continuous-integration build.
19 | set -e
20 |
21 | dir=$(dirname "$0")
22 |
23 | # downloads, unpacks, installs the cloud SDK
24 | source "$dir"/gcloud-init.sh
25 |
26 | cd github/openjdk-runtime
27 | TAG_SUFFIX=$(git rev-parse --short HEAD)
28 |
29 | echo "Invoking build.sh with GCP_PROJECT=$GCP_PROJECT, MODULE=$MODULE, TAG_SUFFIX=$TAG_SUFFIX"
30 | source ./scripts/build.sh --publishing-project "$GCP_PROJECT" --module "$MODULE" --tag-suffix "$TAG_SUFFIX"
31 |
32 | if [ -z "$IMAGE" ]; then
33 | echo "Error: \$IMAGE not defined. It should be exported by build.sh script."
34 | exit 1
35 | fi
36 |
37 |
--------------------------------------------------------------------------------
/scripts/deploy-check-openjdk8.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | export KOKORO_GITHUB_DIR=${KOKORO_ROOT}/src/github
4 | source ${KOKORO_GFILE_DIR}/kokoro/common.sh
5 |
6 | mkdir -p ${KOKORO_GITHUB_DIR}/${SAMPLE_APP_DIRECTORY}
7 |
8 | cd ${KOKORO_GITHUB_DIR}/${SAMPLE_APP_SOURCE_DIRECTORY}
9 |
10 | mvn install --batch-mode -DskipTests -Pruntime.java,deploy.war
11 |
12 | cat < ${KOKORO_GITHUB_DIR}/${SAMPLE_APP_DIRECTORY}/app.yaml
13 | runtime: java
14 | env: flex
15 | runtime_config:
16 | server: jetty9
17 | resources:
18 | memory_gb: 2.5
19 | EOF
20 |
21 | cd ${KOKORO_GFILE_DIR}/appengine/integration_tests
22 |
23 | sudo /usr/local/bin/pip install --upgrade -r requirements.txt
24 |
25 | if [ -f ${KOKORO_GITHUB_DIR}/${SAMPLE_APP_SOURCE_DIRECTORY}/requirements.txt ]
26 | then
27 | sudo /usr/local/bin/pip install --upgrade -r ${KOKORO_GITHUB_DIR}/${SAMPLE_APP_SOURCE_DIRECTORY}/requirements.txt
28 | fi
29 |
30 | export DEPLOY_LATENCY_PROJECT='cloud-deploy-latency'
31 |
32 | skip_flag=""
33 |
34 | if [ "${SKIP_CUSTOM_LOGGING_TESTS}" = "true" -o "${SKIP_BUILDERS}" = "true" ]; then
35 | skip_flag="$skip_flag --skip-builders"
36 | fi
37 |
38 | if [ "${SKIP_XRT}" = "true" ]; then
39 | skip_flag="$skip_flag --skip-xrt"
40 | fi
41 |
42 | python deploy_check.py -d ${KOKORO_GITHUB_DIR}/${SAMPLE_APP_DIRECTORY} -l ${LANGUAGE} ${skip_flag}
43 |
--------------------------------------------------------------------------------
/scripts/gcloud-init.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2016 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 |
18 | # Set up gcloud and auth
19 | set -ex
20 |
21 | DIR=$(pwd)
22 |
23 | if [ -z $GCLOUD_FILE ]; then
24 | echo '$GCLOUD_FILE environment variable must be set.'
25 | exit 1
26 | fi
27 |
28 | if [ -z $KEYFILE ]; then
29 | echo '$KEYFILE environment variable must be set.'
30 | exit 1
31 | fi
32 |
33 | if [ -z $GCP_PROJECT ]; then
34 | echo '$GCP_PROJECT environment variable must be set.'
35 | exit 1
36 | fi
37 |
38 | LOCAL_GCLOUD_FILE=gcloud.tar.gz
39 | cp $GCLOUD_FILE $LOCAL_GCLOUD_FILE
40 |
41 | # Hide the output here, it's long.
42 | tar -xzf $LOCAL_GCLOUD_FILE
43 | export PATH=$DIR/google-cloud-sdk/bin:$PATH
44 |
45 | gcloud auth activate-service-account --key-file=$KEYFILE
46 | gcloud config set project $GCP_PROJECT
47 | gcloud config set compute/zone us-east1-b
48 | gcloud components install beta kubectl -q
49 | gcloud components install beta cloud-build-local
50 |
--------------------------------------------------------------------------------
/scripts/gke_cluster_cleanup.yaml:
--------------------------------------------------------------------------------
1 | # Cloud Builder pipeline for tearing down integration test resources
2 | steps:
3 | - name: 'gcr.io/cloud-builders/gcloud'
4 | args: ['--quiet', 'container', 'clusters', 'delete', '$_CLUSTER_NAME', '--zone=$_ZONE']
5 |
6 |
--------------------------------------------------------------------------------
/scripts/gke_integration_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2017 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Setup environment for CI with GKE.
18 | # This include:
19 | # - Building a test application into a docker image
20 | # - Upload the image to Google Container Registry
21 | # - Create a Kubernetes cluster on GKE
22 | # - Deploy the application
23 | # - Run the integration test
24 | set -e
25 |
26 | readonly dir=$(dirname $0)
27 | readonly projectRoot="$dir/.."
28 | readonly testAppDir="$projectRoot/java-runtimes-common/test-spring-application"
29 | readonly deployDir="$testAppDir/target/deploy"
30 | readonly DEPLOYMENT_TOKEN=$(date -u +%Y-%m-%d-%H-%M-%S-%N)
31 |
32 | # The $TAG was introduced to be able to reuse the existing cluster but force redeployment.
33 | # Kubernetes' "kubectl apply -f" doesn't trigger a new deployment rollout unless there is a change in the yaml spec.
34 | # See https://github.com/kubernetes/kubernetes/issues/33664 for the debate around this behavior.
35 |
36 | if [ -z "${TAG}" ]; then
37 | export TAG="$(date -u +%Y-%m-%d_%H_%M)"
38 | fi
39 |
40 | readonly projectName=$(gcloud info \
41 | | awk '/^Project: / { print $2 }' \
42 | | sed 's/\[//' \
43 | | sed 's/\]//')
44 | readonly imageName="openjdk-gke-integration:$TAG"
45 | readonly imageUrl="gcr.io/$projectName/$imageName"
46 | readonly defaultZone="us-east1-c"
47 |
48 | readonly imageUnderTest=$1
49 | clusterName=$2
50 | if [[ -z "$imageUnderTest" ]]; then
51 | echo "Usage: ${0} [gke_cluster_name]"
52 | exit 1
53 | fi
54 |
55 | if [[ -z "$clusterName" ]]; then
56 | # generate random alpha string
57 | clusterName=$(head /dev/urandom | tr -dc 'a-z' | fold -w 20 | head -n 1)
58 | readonly tearDown="true"
59 | fi
60 |
61 | # build the test app
62 | pushd ${testAppDir}
63 | mvn clean install -Pruntime.custom -Dapp.deploy.image=$imageUnderTest -Ddeployment.token="${DEPLOYMENT_TOKEN}" -DskipTests --batch-mode
64 | popd
65 |
66 | # deploy to Google Kubernetes Engine
67 | pushd ${deployDir}
68 | export TESTED_IMAGE=${imageUrl}
69 | envsubst < "openjdk-spring-boot.yaml.in" > "openjdk-spring-boot.yaml"
70 |
71 | echo "Deploying image to Google Container Registry..."
72 | gcloud docker -- build -t "$imageName" .
73 | gcloud docker -- tag "$imageName" "$imageUrl"
74 | gcloud docker -- push gcr.io/${projectName}/${imageName}
75 |
76 | echo "Creating or searching for a Kubernetes cluster..."
77 | TEST_CLUSTER_EXISTENCE=$(gcloud container clusters list --zone="$defaultZone" | awk "/$clusterName/")
78 | if [ -z "$TEST_CLUSTER_EXISTENCE" ]; then
79 | gcloud container clusters create "$clusterName" --num-nodes=1 --disk-size=10 --zone="$defaultZone"
80 | fi
81 |
82 | echo "Deploying application to Google Kubernetes Engine..."
83 | gcloud container clusters get-credentials ${clusterName} --zone="$defaultZone"
84 | kubectl apply -f "openjdk-spring-boot.yaml"
85 | popd
86 |
87 | echo "Waiting for the application to be accessible (expected time: ~1min)"
88 |
89 | # The load balancer service may take some time to expose the application
90 | # (~ 2 min on the cluster creation)
91 | until [[ $(curl --silent --fail "http://$DEPLOYED_APP_URL/deployment.token" | grep "$DEPLOYMENT_TOKEN") ]]; do
92 | sleep 5
93 | DEPLOYED_APP_URL=$(kubectl describe services openjdk-spring-boot \
94 | | awk '/LoadBalancer Ingress/ { print $3 }')
95 | echo "Current URL for app: $DEPLOYED_APP_URL, deployment token: $DEPLOYMENT_TOKEN. Making sure it accepts connections..."
96 | done
97 |
98 | # run in cloud container builder
99 | echo "Running integration tests on application that is deployed at $DEPLOYED_APP_URL"
100 | gcloud builds submit \
101 | --config ${dir}/integration_test.yaml \
102 | --substitutions "_DEPLOYED_APP_URL=http://$DEPLOYED_APP_URL" \
103 | ${dir}
104 |
105 | # teardown any resources we created
106 | if [ "$tearDown" == "true" ]; then
107 | # run a cleanup build once tests have finished executing
108 | gcloud builds submit \
109 | --config $dir/gke_cluster_cleanup.yaml \
110 | --substitutions "_CLUSTER_NAME=$clusterName,_ZONE=$defaultZone" \
111 | --async \
112 | --no-source
113 | fi
114 |
--------------------------------------------------------------------------------
/scripts/integration_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2017 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Setup environment for CI.
18 | # This script exits as soon as any of the commands in the integration scripts fail
19 | # (including remote failure from Google Cloud Container Builder)
20 | set -e
21 |
22 | readonly dir=`dirname $0`
23 |
24 | imageUnderTest=$1
25 | if [ -z "${imageUnderTest}" ]; then
26 | echo "Usage: ${0} [gae_deployment_version]"
27 | exit 1
28 | fi
29 |
30 | # for local tests it makes sense sometimes to pin the deployment to an
31 | # active version as that will speed up the deployment, for CI/CD this feature
32 | # is not recommended
33 | readonly gaeDeploymentVersion=$2
34 |
35 | ${dir}/local_shutdown_test.sh ${imageUnderTest}
36 |
37 | ${dir}/ae_integration_test.sh ${imageUnderTest} ${gaeDeploymentVersion}
38 |
39 | ${dir}/gke_integration_test.sh ${imageUnderTest}
40 |
--------------------------------------------------------------------------------
/scripts/integration_test.yaml:
--------------------------------------------------------------------------------
1 | # Cloud Builder pipeline for running integration tests
2 | # https://cloud.google.com/container-builder/docs/overview
3 | steps:
4 | # Runtimes-common integration tests
5 | # See https://github.com/GoogleCloudPlatform/runtimes-common/tree/master/integration_tests
6 |
7 | # temporarily we'll depend on our own version until the runtimes-common version is pushed
8 | # - name: 'gcr.io/gcp-runtimes/integration_test'
9 | - name: 'gcr.io/java-runtime-test/integration-test'
10 | args:
11 | - '--url=${_DEPLOYED_APP_URL}'
12 | - '--skip-standard-logging-tests' # blocked by b/33415496
13 | - '--skip-custom-tests'
14 | - '--skip-monitoring-tests'
15 |
16 |
--------------------------------------------------------------------------------
/scripts/integration_test_cleanup.yaml:
--------------------------------------------------------------------------------
1 | # Cloud Builder pipeline for tearing down integration test resources
2 | steps:
3 | - name: 'gcr.io/cloud-builders/gcloud'
4 | args: ['--quiet', 'app', 'versions', 'delete', '$_VERSION']
5 |
6 |
--------------------------------------------------------------------------------
/scripts/local_runtimes_common_integration_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2017 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 |
18 | # exit on command failure
19 | set -e
20 |
21 | readonly dir=$(dirname $0)
22 | readonly projectRoot="$dir/.."
23 | readonly testAppDir="$projectRoot/java-runtimes-common/test-spring-application"
24 | readonly deployDir="$testAppDir/target/deploy"
25 |
26 | APP_IMAGE='openjdk-local-integration'
27 | CONTAINER=${APP_IMAGE}-container
28 | OUTPUT_FILE=${CONTAINER}-output.txt
29 | DEPLOYMENT_TOKEN=$(date -u +%Y-%m-%d-%H-%M-%S-%N)
30 |
31 | readonly imageUnderTest=$1
32 | if [[ -z "$imageUnderTest" ]]; then
33 | echo "Usage: ${0} "
34 | exit 1
35 | fi
36 |
37 | if [[ ! -f $HOME/.config/gcloud/application_default_credentials.json ]]; then
38 | # get default application credentials
39 | gcloud auth application-default login
40 | fi
41 |
42 | # build the test app
43 | pushd ${testAppDir}
44 | mvn clean package -Pruntime.custom -Ddeployment.token="${DEPLOYMENT_TOKEN}" -Dapp.deploy.image=${imageUnderTest} -DskipTests --batch-mode
45 | popd
46 |
47 | # build app container locally
48 | pushd $deployDir
49 | export STAGING_IMAGE=$imageUnderTest
50 | echo "Building app container..."
51 | docker build -t $APP_IMAGE . || docker build -t $APP_IMAGE .
52 |
53 | docker rm -f $CONTAINER || echo "Integration-test-app container is not running, ready to start a new instance."
54 |
55 | # run app container locally to test shutdown logging
56 | echo "Starting app container..."
57 | docker run --rm --name $CONTAINER -p 8080 \
58 | -e "SHUTDOWN_LOGGING_THREAD_DUMP=true" \
59 | -e "SHUTDOWN_LOGGING_HEAP_INFO=true" \
60 | -v "$HOME/.config/gcloud/:/root/.config/gcloud" $APP_IMAGE &> $OUTPUT_FILE &
61 |
62 | function waitForOutput() {
63 | found_output='false'
64 | for run in {1..10}
65 | do
66 | grep "$1" $OUTPUT_FILE && found_output='true' && break
67 | sleep 1
68 | done
69 |
70 | if [ "$found_output" == "false" ]; then
71 | cat $OUTPUT_FILE
72 | echo "did not match '$1' in '$OUTPUT_FILE'"
73 | exit 1
74 | fi
75 | }
76 |
77 | waitForOutput 'Started Application'
78 |
79 | getPort() {
80 | docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{(index $conf 0).HostPort}}{{end}}' ${CONTAINER}
81 | }
82 |
83 |
84 | PORT=`getPort`
85 |
86 | nslookup `hostname` | grep Address | grep -v 127.0 | awk '{print $2}' > /tmp/myip
87 | MYIP=`cat /tmp/myip`
88 |
89 | DEPLOYED_APP_URL=http://$MYIP:$PORT
90 |
91 | echo app is deployed to $DEPLOYED_APP_URL, making sure it accepts connections
92 |
93 |
94 | until [[ $(curl --silent --fail "$DEPLOYED_APP_URL/deployment.token" | grep "$DEPLOYMENT_TOKEN") ]]; do
95 | sleep 2
96 | done
97 | popd
98 |
99 | docker rm -f metadata || echo "ready to run local cloud builder"
100 |
101 | # run in cloud container builder
102 | echo "Running integration tests on application that is deployed at $DEPLOYED_APP_URL"
103 | echo `pwd`
104 | cloud-build-local \
105 | --config ${dir}/integration_test.yaml \
106 | --substitutions "_DEPLOYED_APP_URL=$DEPLOYED_APP_URL" \
107 | --dryrun=false \
108 | ${dir}
109 |
--------------------------------------------------------------------------------
/scripts/local_shutdown_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2017 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 |
18 | # exit on command failure
19 | set -e
20 |
21 | readonly dir=$(dirname $0)
22 | readonly projectRoot="$dir/.."
23 | readonly testAppDir="$projectRoot/java-runtimes-common/test-spring-application"
24 | readonly deployDir="$testAppDir/target/deploy"
25 |
26 | APP_IMAGE='openjdk-local-integration'
27 | CONTAINER=${APP_IMAGE}-container
28 | OUTPUT_FILE=${CONTAINER}-output.txt
29 |
30 | readonly imageUnderTest=$1
31 | if [[ -z "$imageUnderTest" ]]; then
32 | echo "Usage: ${0} "
33 | exit 1
34 | fi
35 |
36 |
37 | pushd ${testAppDir}
38 | mvn clean package -Pruntime.custom -Dapp.deploy.image=$imageUnderTest -DskipTests --batch-mode
39 | popd
40 |
41 | # build app container locally
42 | pushd $deployDir
43 | echo "Building app container..."
44 | docker build -t $APP_IMAGE . || gcloud docker -- build -t $APP_IMAGE .
45 |
46 | docker rm -f $CONTAINER || echo "Integration-test-app container is not running, ready to start a new instance."
47 |
48 | # run app container locally to test shutdown logging
49 | # as ServiceOptions.getDefaultProjectId takes 2 minutes to timeout on Argo
50 | # builds, when using "sibling" containers, we use --net=host to make the call
51 | # to the metadata server faster
52 |
53 | echo "Starting app container..."
54 | docker run --rm --memory="1g" --net=host --name $CONTAINER -e "SHUTDOWN_LOGGING_THREAD_DUMP=true" -e "SHUTDOWN_LOGGING_HEAP_INFO=true" $APP_IMAGE &> $OUTPUT_FILE &
55 |
56 | function waitForOutput() {
57 | found_output='false'
58 | for run in {1..20}
59 | do
60 | grep -P "$1" $OUTPUT_FILE && found_output='true' && break
61 | sleep 1
62 | done
63 |
64 | if [ "$found_output" == "false" ]; then
65 | cat $OUTPUT_FILE
66 | echo "did not match '$1' in '$OUTPUT_FILE'"
67 | exit 1
68 | fi
69 | }
70 |
71 | waitForOutput 'Started Application'
72 |
73 | docker stop $CONTAINER
74 |
75 | docker rmi $APP_IMAGE
76 |
77 | echo 'verify thread dump'
78 | waitForOutput 'Full thread dump OpenJDK 64-Bit Server VM'
79 |
80 | echo 'verify heap info'
81 | waitForOutput '\d+:\s+\d+\s+\d+\s+java.lang.Class'
82 |
83 | popd
84 |
85 | echo 'OK'
86 |
--------------------------------------------------------------------------------
/scripts/release-openjdk.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | export KOKORO_GITHUB_DIR=${KOKORO_ROOT}/src/github
3 | source ${KOKORO_GFILE_DIR}/kokoro/common.sh
4 |
5 | cd ${KOKORO_GITHUB_DIR}/openjdk-runtime
6 |
7 | params="--publishing-project ${PUBLISHING_PROJECT} --staging-project ${GCP_TEST_PROJECT} --module ${MODULE}"
8 | if [ -n "${TAG_SUFFIX}" ]; then
9 | params="$params --tag-suffix ${TAG_SUFFIX}"
10 | fi
11 |
12 | source ./scripts/build.sh ${params}
--------------------------------------------------------------------------------
/scripts/structure_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2016 Google Inc. All rights reserved.
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | #
18 | # Fetch and execute the structure test framework run script.
19 | set -e
20 |
21 | dir=`dirname $0`
22 | scriptPath=https://storage.googleapis.com/container-structure-test/v1.1.0/container-structure-test
23 | destDir=$dir/../target
24 | fileName=$destDir/container-structure-test
25 |
26 | if [ ! -d $destDir ]
27 | then
28 | mkdir -p $destDir
29 | fi
30 |
31 | wget -O $fileName --no-verbose $scriptPath
32 | chmod +x $fileName
33 |
34 | IMAGE=$1
35 | WORKSPACE=$2
36 | CONFIG=$3
37 | TEST_IMAGE="${IMAGE}-struct-test"
38 |
39 | pushd `pwd`
40 | cd $WORKSPACE
41 | echo "Creating temporary image $TEST_IMAGE"
42 | cat < Dockerfile
43 | FROM $IMAGE
44 | ADD . /workspace
45 | EOF
46 | docker build -t $TEST_IMAGE .
47 | rm Dockerfile
48 | popd
49 |
50 | $fileName test --image $TEST_IMAGE --config $CONFIG
51 |
52 |
--------------------------------------------------------------------------------