diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml
index 7c20f065f48..12d9f01d7b7 100644
--- a/.github/sync-repo-settings.yaml
+++ b/.github/sync-repo-settings.yaml
@@ -7,6 +7,7 @@ branchProtectionRules:
requiredStatusCheckContexts:
- 'Kokoro CI - Java 11'
- 'Kokoro CI - Java 8'
+ - 'Kokoro CI - Java 17'
- 'Kokoro CI - Lint'
- 'cla/google'
requiredApprovingReviewCount: 1
diff --git a/.kokoro/java17/common.cfg b/.kokoro/java17/common.cfg
new file mode 100644
index 00000000000..0ee5c4bf978
--- /dev/null
+++ b/.kokoro/java17/common.cfg
@@ -0,0 +1,45 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build timeout of 5 hours
+timeout_mins: 360
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "java-docs-samples/.kokoro/trampoline.sh"
+
+action {
+ define_artifacts {
+ regex: "**/*sponge_log.xml"
+ }
+}
+
+# Set the JAVA VERSION env var.
+env_vars: {
+ key: "JAVA_VERSION"
+ value: "1.8,11,17"
+}
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE"
+ value: "gcr.io/cloud-devrel-kokoro-resources/java17"
+}
+
+# Access btlr binaries used in the tests
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/btlr"
diff --git a/.kokoro/java17/continuous.cfg b/.kokoro/java17/continuous.cfg
new file mode 100644
index 00000000000..d9a8c1bffdc
--- /dev/null
+++ b/.kokoro/java17/continuous.cfg
@@ -0,0 +1,27 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Tell trampoline which tests to run.
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/java-docs-samples/.kokoro/tests/run_tests.sh"
+}
+
+# Only diff from previous commit
+env_vars: {
+ key: "GIT_DIFF"
+ value: "HEAD~.. ."
+}
diff --git a/.kokoro/java17/periodic.cfg b/.kokoro/java17/periodic.cfg
new file mode 100644
index 00000000000..65cbde07819
--- /dev/null
+++ b/.kokoro/java17/periodic.cfg
@@ -0,0 +1,22 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Tell the trampoline which build file to use.
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/java-docs-samples/.kokoro/tests/run_tests.sh"
+}
+
diff --git a/.kokoro/java17/presubmit.cfg b/.kokoro/java17/presubmit.cfg
new file mode 100644
index 00000000000..f642ed9fdf6
--- /dev/null
+++ b/.kokoro/java17/presubmit.cfg
@@ -0,0 +1,26 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Tell the trampoline which build file to use.
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/java-docs-samples/.kokoro/tests/run_tests.sh"
+}
+# Only diff from main
+env_vars: {
+ key: "GIT_DIFF"
+ value: "origin/main... ."
+}
diff --git a/.kokoro/tests/run_test_java.sh b/.kokoro/tests/run_test_java.sh
index 39cf1f78775..f645e881171 100755
--- a/.kokoro/tests/run_test_java.sh
+++ b/.kokoro/tests/run_test_java.sh
@@ -18,7 +18,7 @@ SCRIPT_DIR="$(dirname $0)/"
# Fail the tests if no Java version was found.
POM_JAVA=$(grep -oP '(?<=).*?(?=)' pom.xml)
-ALLOWED_VERSIONS=("1.8" "11")
+ALLOWED_VERSIONS=("1.8" "11" "17")
# shellcheck disable=SC2199
# shellcheck disable=SC2076
if [[ "$POM_JAVA" = "" ]] || [[ ! "${ALLOWED_VERSIONS[@]}" =~ "${POM_JAVA}" ]]; then
diff --git a/.kokoro/tests/run_tests.sh b/.kokoro/tests/run_tests.sh
index 73f3690fbf8..a7d7071d0d3 100755
--- a/.kokoro/tests/run_tests.sh
+++ b/.kokoro/tests/run_tests.sh
@@ -45,6 +45,8 @@ if [[ "$SCRIPT_DEBUG" != "true" ]]; then
# Update `gcloud` and log versioning for debugging
apt update && apt -y upgrade google-cloud-sdk
+ echo "********** GIT INFO ***********"
+ git version
echo "********** GCLOUD INFO ***********"
gcloud -v
echo "********** MAVEN INFO ***********"
@@ -115,6 +117,8 @@ fi
echo -e "\n******************** TESTING PROJECTS ********************"
test_prog="$PWD/.kokoro/tests/run_test_java.sh"
+git config --global --add safe.directory $PWD
+
# Use btlr to run all the tests in each folder
echo "btlr" "${btlr_args[@]}" -- "${test_prog}"
btlr "${btlr_args[@]}" -- "${test_prog}"
diff --git a/README.md b/README.md
index 9f8c938af38..e8a06cd1398 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,10 @@ This repository holds sample code written in Java that demonstrates the
Some samples have accompanying guides on . See respective
README files for details.
+## Google Cloud Samples
+
+To browse ready to use code samples check [Google Cloud Samples](https://cloud.google.com/docs/samples?l=java).
+
## Set Up
1. [Set up your Java Development Environment](https://cloud.google.com/java/docs/setup)
diff --git a/appengine-java11-bundled-services/README.md b/appengine-java11-bundled-services/README.md
index e07e46db7c9..700f8fb1de2 100644
--- a/appengine-java11-bundled-services/README.md
+++ b/appengine-java11-bundled-services/README.md
@@ -39,9 +39,10 @@ access control, billing, and services.
## Development differences between App Engine Java8 and Java11 Bundled Services
-The only difference between a Java8 application and a Java11 application is in the `appengine-web.xml` file
+The only differences between a Java8 application and a Java11 application are the addition of the bundled services JAR, and an added line in the `appengine-web.xml` file
where you need to define the Java11 runtime and declare you need the App Engine APIs:
+In `appengine-web.xml`:
```XML
java11
@@ -49,10 +50,18 @@ where you need to define the Java11 runtime and declare you need the App Engine
```
-While the Java11 runtime is in Beta, in order to deploy the application, you can use the `beta` value for the `gcloudMode` Cloud SDK parameter like:
+In your `pom.xml`'s ``:
+```XML
+
+ com.google.appengine
+ appengine-api-1.0-sdk
+ 2.0.4
+
+```
+
```shell
- mvn appengine:deploy -Dapp.deploy.gcloudMode=beta
+ mvn appengine:deploy
```
@@ -72,17 +81,17 @@ This sample demonstrates how to use the App Engine Datastore APIs in a Java11 we
You can execute the following steps to transform the java8 appengine-web.xml file to a java11 appengine-web.xml file:
- ```shell
- git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
- cd java-docs-samples
- cp -pr appengine-java8 /tmp/java11-samples
- cd /tmp/java11-samples
- # On Linux:
- shopt -s globstar dotglob
- for f in **/appengine-web.xml; do sed -i 's.java8.java11true.' ${f}; done
- # on MacOS
- for f in **/appengine-web.xml; do sed -i'' -e 's.java8.java11true.' ${f}; done
- ```
+```shell
+git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
+cd java-docs-samples
+cp -pr appengine-java8 /tmp/java11-samples
+cd /tmp/java11-samples
+# On Linux:
+shopt -s globstar dotglob
+for f in **/appengine-web.xml; do sed -i 's.java8.java11true.' ${f}; done
+# on MacOS
+for f in **/appengine-web.xml; do sed -i'' -e 's.java8.java11true.' ${f}; done
+ ```
You will see in the `tmp/java11` directory all the correct code samples to compile and deploy to the Java11 AppEngine runtime, with bundled services.
Just follow the same documentation as the [Java8 samples][java8-samples].
diff --git a/appengine-java11-bundled-services/datastore/README.md b/appengine-java11-bundled-services/datastore/README.md
index 38fe704b9f8..bbf66ef0e81 100644
--- a/appengine-java11-bundled-services/datastore/README.md
+++ b/appengine-java11-bundled-services/datastore/README.md
@@ -39,10 +39,7 @@ To see the results of the sample application, open
## Deploying
-In the following command, replace YOUR-PROJECT-ID with your
-[Google Cloud Project ID](https://developers.google.com/console/help/new/#projectnumber)
-and SOME-VERSION with a valid version number.
-
```sh
mvn clean package appengine:deploy
+mvn appengine:deployIndex
```
diff --git a/appengine-java11-bundled-services/datastore/pom.xml b/appengine-java11-bundled-services/datastore/pom.xml
index 6b05b4830b5..47624da98de 100644
--- a/appengine-java11-bundled-services/datastore/pom.xml
+++ b/appengine-java11-bundled-services/datastore/pom.xml
@@ -126,10 +126,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java11/cloudsql/pom.xml b/appengine-java11/cloudsql/pom.xml
index 06be5c6ba5a..40a7f88b63d 100644
--- a/appengine-java11/cloudsql/pom.xml
+++ b/appengine-java11/cloudsql/pom.xml
@@ -73,13 +73,13 @@
mysql
mysql-connector-java
- 8.0.28
+ 8.0.29
provided
com.google.cloud.sql
mysql-socket-factory-connector-j-8
- 1.5.0
+ 1.6.0
provided
@@ -92,7 +92,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -156,7 +156,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
cloudsql
diff --git a/appengine-java11/gaeinfo/pom.xml b/appengine-java11/gaeinfo/pom.xml
index 0b05b4ca69c..d73205a3363 100644
--- a/appengine-java11/gaeinfo/pom.xml
+++ b/appengine-java11/gaeinfo/pom.xml
@@ -84,7 +84,7 @@ Copyright 2019 Google LLC
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
gaeinfo
diff --git a/appengine-java11/guestbook-cloud-firestore/pom.xml b/appengine-java11/guestbook-cloud-firestore/pom.xml
index cc659d64be1..12cc6bdab0c 100644
--- a/appengine-java11/guestbook-cloud-firestore/pom.xml
+++ b/appengine-java11/guestbook-cloud-firestore/pom.xml
@@ -91,10 +91,15 @@
guestbook
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
guestbook
diff --git a/appengine-java11/helloworld-servlet/pom.xml b/appengine-java11/helloworld-servlet/pom.xml
index 7fd26821f8d..b2050c08b25 100644
--- a/appengine-java11/helloworld-servlet/pom.xml
+++ b/appengine-java11/helloworld-servlet/pom.xml
@@ -67,10 +67,15 @@ limitations under the License.
helloworld
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
helloworld
diff --git a/appengine-java11/http-server/pom.xml b/appengine-java11/http-server/pom.xml
index 4a8724776d2..53a51c8dcbc 100644
--- a/appengine-java11/http-server/pom.xml
+++ b/appengine-java11/http-server/pom.xml
@@ -38,7 +38,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
http-server
diff --git a/appengine-java11/kotlin-ktor/app.yaml b/appengine-java11/kotlin-ktor/app.yaml
index 7d200ea8834..ad7258b8290 100644
--- a/appengine-java11/kotlin-ktor/app.yaml
+++ b/appengine-java11/kotlin-ktor/app.yaml
@@ -13,4 +13,3 @@
# limitations under the License.
runtime: java11
-entrypoint: 'java -jar target/kotlin-ktor-0.0.1-jar-with-dependencies.jar'
diff --git a/appengine-java11/kotlin-ktor/pom.xml b/appengine-java11/kotlin-ktor/pom.xml
index f459f8ee62d..e480653d73d 100644
--- a/appengine-java11/kotlin-ktor/pom.xml
+++ b/appengine-java11/kotlin-ktor/pom.xml
@@ -31,156 +31,138 @@ limitations under the License.
+ 11
+ 11
+ 2.0.2-eap-389
official
+ 1.6.21
+ 1.2.11
UTF-8
true
- io.ktor.server.netty.EngineMain
- 11
- 11
+ com.example.appengine.ApplicationKt
- repo1
- https://jcenter.bintray.com
- true
- false
-
-
- repo2
- https://kotlin.bintray.com/ktor
- true
- false
+ ktor_eap
+ https://maven.pkg.jetbrains.space/public/p/ktor/eap
+
+ true
+
+
+ true
+
-
-
-
- io.ktor
- ktor-bom
- 1.6.8
- pom
- import
-
-
-
-
- org.jetbrains.kotlin
- kotlin-stdlib-jdk8
- 1.6.20
-
-
- io.ktor
- ktor-server-netty
-
-
- ch.qos.logback
- logback-classic
- 1.3.0-alpha11
+ io.ktor
+ ktor-server-core-jvm
+ ${ktor_version}
- io.ktor
- ktor-server-core
+ io.ktor
+ ktor-server-netty-jvm
+ ${ktor_version}
- io.ktor
- ktor-server-host-common
+ ch.qos.logback
+ logback-classic
+ ${logback_version}
- io.ktor
- ktor-server-tests
- test
+ io.ktor
+ ktor-server-tests-jvm
+ ${ktor_version}
+ test
- org.jetbrains.kotlin
- kotlin-test-junit
- 1.6.20
- test
+ org.jetbrains.kotlin
+ kotlin-test-junit
+ ${kotlin_version}
+ test
-
-
-
-
- ${project.basedir}/src
- ${project.basedir}/test
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/test/kotlin
-
- ${project.basedir}/resources
-
+
+ ${project.basedir}/src/main/resources
+
+
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- maven-compiler-plugin
- 1.81.8
-
-
- kotlin-maven-plugin
- org.jetbrains.kotlin
- 1.6.20
-
-
- compile
- compile
+
+ kotlin-maven-plugin
+ org.jetbrains.kotlin
+ ${kotlin_version}
- enable
+ 1.8
-
-
- test-compile
- test-compile
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.0.0
+
+
+
+ java
+
+
+
- enable
+ ${main.class}
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.2.2
-
-
-
- true
- ${main.class}
-
-
-
-
-
- org.apache.maven.plugins
- maven-assembly-plugin
- 3.3.0
-
-
- make-assembly
- package
- single
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.6
-
-
- ${main.class}
-
-
-
- jar-with-dependencies
-
+
+ jar-with-dependencies
+
+
+
+ true
+ ${main.class}
+
+
-
-
-
+
+
+ assemble-all
+ package
+
+ single
+
+
+
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
kotlin-ktor
diff --git a/appengine-java11/kotlin-ktor/src/Application.kt b/appengine-java11/kotlin-ktor/src/main/kotlin/com/example/appengine/Application.kt
similarity index 67%
rename from appengine-java11/kotlin-ktor/src/Application.kt
rename to appengine-java11/kotlin-ktor/src/main/kotlin/com/example/appengine/Application.kt
index c5d623b1cba..3325d31456c 100644
--- a/appengine-java11/kotlin-ktor/src/Application.kt
+++ b/appengine-java11/kotlin-ktor/src/main/kotlin/com/example/appengine/Application.kt
@@ -14,22 +14,16 @@
package com.example.appengine
-import io.ktor.application.Application
-import io.ktor.application.call
-import io.ktor.application.install
import io.ktor.http.ContentType
-import io.ktor.response.respondText
-import io.ktor.routing.get
-import io.ktor.routing.routing
-import io.ktor.server.engine.ShutDownUrl
-import io.ktor.server.netty.EngineMain
+import io.ktor.server.application.*
+import io.ktor.server.engine.*
+import io.ktor.server.response.*
+import io.ktor.server.routing.*
-fun main(args: Array): Unit = EngineMain.main(args)
+fun main(args: Array): Unit = io.ktor.server.netty.EngineMain.main(args)
-@Suppress("unused") // Referenced in application.conf
-@kotlin.jvm.JvmOverloads
-fun Application.module(testing: Boolean = false) {
- install(ShutDownUrl.ApplicationCallFeature) {
+fun Application.module() {
+ install(ShutDownUrl.ApplicationCallPlugin) {
// The URL that will be intercepted. You can also use the
// application.conf's ktor.deployment.shutdown.url key.
shutDownUrl = "/_ah/stop"
@@ -37,10 +31,10 @@ fun Application.module(testing: Boolean = false) {
// A function that will be executed to get the exit code of the process
exitCodeSupplier = { 0 } // ApplicationCall.() -> Int
}
-
routing {
get("/") {
call.respondText("Hello World!", contentType = ContentType.Text.Plain)
}
}
}
+
diff --git a/appengine-java11/kotlin-ktor/src/main/resources/application.conf b/appengine-java11/kotlin-ktor/src/main/resources/application.conf
new file mode 100644
index 00000000000..4cd0bfa8317
--- /dev/null
+++ b/appengine-java11/kotlin-ktor/src/main/resources/application.conf
@@ -0,0 +1,26 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ktor {
+ deployment {
+ port = 8080
+ port = ${?PORT}
+
+ shutdown.url = "/_ah/stop"
+ }
+ application {
+ modules = [ com.example.appengine.ApplicationKt.module ]
+ }
+}
+
diff --git a/appengine-java11/kotlin-ktor/src/main/resources/logback.xml b/appengine-java11/kotlin-ktor/src/main/resources/logback.xml
new file mode 100644
index 00000000000..bdbb64ec4ba
--- /dev/null
+++ b/appengine-java11/kotlin-ktor/src/main/resources/logback.xml
@@ -0,0 +1,12 @@
+
+
+
+ %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
diff --git a/appengine-java11/kotlin-ktor/src/test/ApplicationTest.kt b/appengine-java11/kotlin-ktor/src/test/ApplicationTest.kt
new file mode 100644
index 00000000000..9450ef165bd
--- /dev/null
+++ b/appengine-java11/kotlin-ktor/src/test/ApplicationTest.kt
@@ -0,0 +1,35 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.example.appengine
+
+import io.ktor.server.http.HttpMethod
+import io.ktor.server.http.HttpStatusCode
+import io.ktor.server.testing.handleRequest
+import io.ktor.server.testing.withTestApplication
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class ApplicationTest {
+ @Test
+ fun testRoot() {
+ withTestApplication({ module(testing = true) }) {
+ handleRequest(HttpMethod.Get, "/").apply {
+ assertEquals(HttpStatusCode.OK, response.status())
+ assertEquals("Hello World!", response.content)
+ }
+ }
+ }
+}
+
diff --git a/appengine-java11/micronaut-helloworld/pom.xml b/appengine-java11/micronaut-helloworld/pom.xml
index 700a87ae77f..8faafbed2aa 100644
--- a/appengine-java11/micronaut-helloworld/pom.xml
+++ b/appengine-java11/micronaut-helloworld/pom.xml
@@ -33,7 +33,7 @@
com.example.appengine.Application
11
11
- 3.4.1
+ 3.4.3
@@ -86,7 +86,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
micronaut-helloworld
diff --git a/appengine-java11/oauth2/pom.xml b/appengine-java11/oauth2/pom.xml
index fd4179456d3..a4688d78266 100644
--- a/appengine-java11/oauth2/pom.xml
+++ b/appengine-java11/oauth2/pom.xml
@@ -57,14 +57,14 @@
com.google.oauth-client
google-oauth-client
- 1.33.2
+ 1.33.3
provided
com.google.oauth-client
google-oauth-client-servlet
- 1.33.2
+ 1.33.3
provided
@@ -77,7 +77,7 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
@@ -101,10 +101,15 @@
oauth2
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
oauth2
diff --git a/appengine-java11/quarkus-helloworld/pom.xml b/appengine-java11/quarkus-helloworld/pom.xml
index 8841535d0a8..66cbce5ff2c 100644
--- a/appengine-java11/quarkus-helloworld/pom.xml
+++ b/appengine-java11/quarkus-helloworld/pom.xml
@@ -32,7 +32,7 @@ limitations under the License.
2.22.2
11
11
- 2.8.0.Final
+ 2.9.0.Final
UTF-8
@@ -92,7 +92,7 @@ limitations under the License.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
quarkus-helloworld
diff --git a/appengine-java11/spanner/pom.xml b/appengine-java11/spanner/pom.xml
index b908c9b7846..d14382d263e 100644
--- a/appengine-java11/spanner/pom.xml
+++ b/appengine-java11/spanner/pom.xml
@@ -108,7 +108,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
spanner
diff --git a/appengine-java11/sparkjava-helloworld/pom.xml b/appengine-java11/sparkjava-helloworld/pom.xml
index 6969e3e012f..6cbfa144f30 100644
--- a/appengine-java11/sparkjava-helloworld/pom.xml
+++ b/appengine-java11/sparkjava-helloworld/pom.xml
@@ -101,7 +101,7 @@ limitations under the License.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
${project.build.directory}/sparkjava-helloworld-1.0-jar-with-dependencies.jar
diff --git a/appengine-java11/springboot-helloworld/pom.xml b/appengine-java11/springboot-helloworld/pom.xml
index a186992352a..7abe625b9ef 100644
--- a/appengine-java11/springboot-helloworld/pom.xml
+++ b/appengine-java11/springboot-helloworld/pom.xml
@@ -92,7 +92,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
+
+ 4.0.0
+ war
+ 1.0-SNAPSHOT
+ com.example.appengine
+ appengine-datastore-j17
+
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.2.0
+
+
+
+ 11
+ 11
+
+
+
+
+ com.google.appengine
+ appengine-api-1.0-sdk
+ 2.0.4
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ jar
+ provided
+
+
+
+ com.google.auto.value
+ auto-value
+ 1.9
+ provided
+
+
+
+ com.google.auto.value
+ auto-value-annotations
+ 1.9
+
+
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+
+
+
+ com.google.guava
+ guava
+ 31.0.1-jre
+
+
+
+ joda-time
+ joda-time
+ 2.10.13
+
+
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.10.19
+ test
+
+
+
+ com.google.appengine
+ appengine-testing
+ 2.0.4
+ test
+
+
+ com.google.appengine
+ appengine-api-stubs
+ 2.0.4
+ test
+
+
+ com.google.appengine
+ appengine-tools-sdk
+ 2.0.4
+ test
+
+
+ com.google.truth
+ truth
+ 1.1.3
+ test
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+
+ maven-war-plugin
+ 3.3.1
+
+
+ default-war
+ package
+
+ war
+
+
+
+
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.4.1
+
+ GCLOUD_CONFIG
+ GCLOUD_CONFIG
+ beta
+ true
+ true
+
+
+
+
+ maven-compiler-plugin
+ 3.8.1
+
+
+
+ com.google.auto.value
+ auto-value
+ 1.9
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-maven-plugin
+ 9.4.44.v20210927
+
+
+
+
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/AbstractGuestbook.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/AbstractGuestbook.java
new file mode 120000
index 00000000000..59b8bfc0057
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/AbstractGuestbook.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/AbstractGuestbook.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/AbstractGuestbookServlet.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/AbstractGuestbookServlet.java
new file mode 120000
index 00000000000..a91e7e09658
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/AbstractGuestbookServlet.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/AbstractGuestbookServlet.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/Greeting.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/Greeting.java
new file mode 120000
index 00000000000..9c59e2047b8
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/Greeting.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/Greeting.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/Guestbook.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/Guestbook.java
new file mode 120000
index 00000000000..2e3d8e4b664
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/Guestbook.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/Guestbook.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookServlet.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookServlet.java
new file mode 120000
index 00000000000..752427a8057
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookServlet.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/GuestbookServlet.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookStrong.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookStrong.java
new file mode 120000
index 00000000000..fef89e36ba8
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookStrong.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/GuestbookStrong.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookStrongServlet.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookStrongServlet.java
new file mode 120000
index 00000000000..f2d53752473
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/GuestbookStrongServlet.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/GuestbookStrongServlet.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/ListPeopleServlet.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/ListPeopleServlet.java
new file mode 120000
index 00000000000..fc42fbc3dcd
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/ListPeopleServlet.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/ListPeopleServlet.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/ProjectionServlet.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/ProjectionServlet.java
new file mode 120000
index 00000000000..ceb105b6acf
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/ProjectionServlet.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/ProjectionServlet.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/StartupServlet.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/StartupServlet.java
new file mode 120000
index 00000000000..eae75ba9016
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/StartupServlet.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/StartupServlet.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/StatsServlet.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/StatsServlet.java
new file mode 120000
index 00000000000..6502647321e
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/appengine/StatsServlet.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/appengine/StatsServlet.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/Clock.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/Clock.java
new file mode 120000
index 00000000000..2413e2ddc58
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/Clock.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/time/Clock.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/SystemClock.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/SystemClock.java
new file mode 120000
index 00000000000..4193c4824ac
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/SystemClock.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/main/java/com/example/time/SystemClock.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/testing/FakeClock.java b/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/testing/FakeClock.java
new file mode 120000
index 00000000000..b963230e3c4
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/java/com/example/time/testing/FakeClock.java
@@ -0,0 +1 @@
+../../../../../../../../../appengine-java8/datastore/src/main/java/com/example/time/testing/FakeClock.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 00000000000..d934ac71f3a
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,17 @@
+
+
+
+ java17
+ true
+
diff --git a/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/datastore-indexes.xml b/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/datastore-indexes.xml
new file mode 120000
index 00000000000..73f343b36e4
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/datastore-indexes.xml
@@ -0,0 +1 @@
+../../../../../../appengine-java8/datastore/src/main/webapp/WEB-INF/datastore-indexes.xml
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/web.xml b/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/web.xml
new file mode 120000
index 00000000000..6c846cab2a4
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1 @@
+../../../../../../appengine-java8/datastore/src/main/webapp/WEB-INF/web.xml
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/main/webapp/guestbook.jsp b/appengine-java17-bundled-services/datastore/src/main/webapp/guestbook.jsp
new file mode 120000
index 00000000000..dc4c9b4a240
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/main/webapp/guestbook.jsp
@@ -0,0 +1 @@
+../../../../../appengine-java8/datastore/src/main/webapp/guestbook.jsp
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/EntitiesTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/EntitiesTest.java
new file mode 120000
index 00000000000..6acecc301aa
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/EntitiesTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/EntitiesTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/GuestbookStrongTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/GuestbookStrongTest.java
new file mode 120000
index 00000000000..3541f8f82bb
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/GuestbookStrongTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/GuestbookStrongTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/GuestbookTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/GuestbookTest.java
new file mode 120000
index 00000000000..015e621216b
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/GuestbookTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/GuestbookTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/IndexesTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/IndexesTest.java
new file mode 120000
index 00000000000..2530a9646f2
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/IndexesTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/IndexesTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ListPeopleServletTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ListPeopleServletTest.java
new file mode 120000
index 00000000000..e32bdc25149
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ListPeopleServletTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/ListPeopleServletTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataEntityGroupTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataEntityGroupTest.java
new file mode 120000
index 00000000000..97be437f7c1
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataEntityGroupTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/MetadataEntityGroupTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataKindsTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataKindsTest.java
new file mode 120000
index 00000000000..aedd248bc2b
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataKindsTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/MetadataKindsTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataNamespacesTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataNamespacesTest.java
new file mode 120000
index 00000000000..02eea767d46
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataNamespacesTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/MetadataNamespacesTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataPropertiesTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataPropertiesTest.java
new file mode 120000
index 00000000000..d94057bf260
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/MetadataPropertiesTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/MetadataPropertiesTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ProjectionServletTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ProjectionServletTest.java
new file mode 120000
index 00000000000..f442793b9c6
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ProjectionServletTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/ProjectionServletTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ProjectionTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ProjectionTest.java
new file mode 120000
index 00000000000..99cd3ef139a
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ProjectionTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/ProjectionTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/QueriesTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/QueriesTest.java
new file mode 120000
index 00000000000..2b4c7b4c7fc
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/QueriesTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/QueriesTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ReadPolicyTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ReadPolicyTest.java
new file mode 120000
index 00000000000..84a38cfa093
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/ReadPolicyTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/ReadPolicyTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/StartupServletTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/StartupServletTest.java
new file mode 120000
index 00000000000..cc898f78bbb
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/StartupServletTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/StartupServletTest.java
\ No newline at end of file
diff --git a/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/TransactionsTest.java b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/TransactionsTest.java
new file mode 120000
index 00000000000..8c3e828ead3
--- /dev/null
+++ b/appengine-java17-bundled-services/datastore/src/test/java/com/example/appengine/TransactionsTest.java
@@ -0,0 +1 @@
+../../../../../../../../appengine-java8/datastore/src/test/java/com/example/appengine/TransactionsTest.java
\ No newline at end of file
diff --git a/appengine-java8/analytics/pom.xml b/appengine-java8/analytics/pom.xml
index 61d62586712..c7f58045cad 100644
--- a/appengine-java8/analytics/pom.xml
+++ b/appengine-java8/analytics/pom.xml
@@ -87,7 +87,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -107,10 +107,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
analytics
diff --git a/appengine-java8/appidentity/pom.xml b/appengine-java8/appidentity/pom.xml
index e9d76a9bb9a..e6a15292f82 100644
--- a/appengine-java8/appidentity/pom.xml
+++ b/appengine-java8/appidentity/pom.xml
@@ -105,10 +105,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/bigquery/pom.xml b/appengine-java8/bigquery/pom.xml
index 9ce1b14361a..2a24e6d5022 100644
--- a/appengine-java8/bigquery/pom.xml
+++ b/appengine-java8/bigquery/pom.xml
@@ -57,7 +57,7 @@
com.google.cloud
google-cloud-monitoring
- 3.2.7
+ 3.2.9
@@ -94,7 +94,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -117,7 +117,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/bigtable/build.gradle b/appengine-java8/bigtable/build.gradle
index 4cfaf44aba1..63332506c3e 100644
--- a/appengine-java8/bigtable/build.gradle
+++ b/appengine-java8/bigtable/build.gradle
@@ -18,7 +18,7 @@ buildscript { // Configuration for building
mavenCentral()
}
dependencies {
- classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2'
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.3'
classpath 'org.akhikhl.gretty:gretty:+'
}
}
@@ -46,7 +46,7 @@ repositories {
dependencies {
compile group: 'com.google.cloud.bigtable', name: 'bigtable-hbase-1.2', version:'1.0.0-pre3'
- compile group: 'org.apache.hbase', name: 'hbase-client', version:'2.4.11'
+ compile group: 'org.apache.hbase', name: 'hbase-client', version:'2.4.12'
compile group: 'io.netty', name: 'netty-tcnative-boringssl-static', version:'2.0.50.Final'
compile group: 'jstl', name: 'jstl', version:'1.2'
diff --git a/appengine-java8/bigtable/pom.xml b/appengine-java8/bigtable/pom.xml
index 61fe21a82b9..2ede3685309 100644
--- a/appengine-java8/bigtable/pom.xml
+++ b/appengine-java8/bigtable/pom.xml
@@ -47,7 +47,7 @@ limitations under the License.
com.google.cloud.bigtable
bigtable-hbase-1.x-hadoop
- 2.1.0
+ 2.2.0
@@ -138,7 +138,7 @@ limitations under the License.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/datastore-indexes-exploding/pom.xml b/appengine-java8/datastore-indexes-exploding/pom.xml
index ff5d41082e5..aea3f4099ec 100644
--- a/appengine-java8/datastore-indexes-exploding/pom.xml
+++ b/appengine-java8/datastore-indexes-exploding/pom.xml
@@ -92,10 +92,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/datastore-indexes-perfect/pom.xml b/appengine-java8/datastore-indexes-perfect/pom.xml
index d7f1f4671a8..cf5bfdc4200 100644
--- a/appengine-java8/datastore-indexes-perfect/pom.xml
+++ b/appengine-java8/datastore-indexes-perfect/pom.xml
@@ -92,10 +92,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/datastore-indexes/pom.xml b/appengine-java8/datastore-indexes/pom.xml
index 3e2471378ec..54ded644380 100644
--- a/appengine-java8/datastore-indexes/pom.xml
+++ b/appengine-java8/datastore-indexes/pom.xml
@@ -93,10 +93,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/datastore-schedule-export/pom.xml b/appengine-java8/datastore-schedule-export/pom.xml
index 0d2f7e9c973..eec7b45a92d 100644
--- a/appengine-java8/datastore-schedule-export/pom.xml
+++ b/appengine-java8/datastore-schedule-export/pom.xml
@@ -82,10 +82,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/datastore/pom.xml b/appengine-java8/datastore/pom.xml
index 0464f7098c6..a26012c2bf7 100644
--- a/appengine-java8/datastore/pom.xml
+++ b/appengine-java8/datastore/pom.xml
@@ -125,10 +125,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/endpoints-v2-backend/build.gradle b/appengine-java8/endpoints-v2-backend/build.gradle
index 8777ff8038c..434d39f0c31 100644
--- a/appengine-java8/endpoints-v2-backend/build.gradle
+++ b/appengine-java8/endpoints-v2-backend/build.gradle
@@ -21,7 +21,7 @@ buildscript {
// [START endpoints_plugin]
classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:2.1.0'
// [END endpoints_plugin]
- classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2'
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.3'
}
}
diff --git a/appengine-java8/endpoints-v2-backend/pom.xml b/appengine-java8/endpoints-v2-backend/pom.xml
index d03326d3014..1dd03821a3a 100644
--- a/appengine-java8/endpoints-v2-backend/pom.xml
+++ b/appengine-java8/endpoints-v2-backend/pom.xml
@@ -98,7 +98,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
diff --git a/appengine-java8/endpoints-v2-guice/build.gradle b/appengine-java8/endpoints-v2-guice/build.gradle
index bdf9f22b74e..bbb641df97c 100644
--- a/appengine-java8/endpoints-v2-guice/build.gradle
+++ b/appengine-java8/endpoints-v2-guice/build.gradle
@@ -19,7 +19,7 @@ buildscript {
dependencies {
classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:2.1.0'
- classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2'
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.3'
}
}
diff --git a/appengine-java8/endpoints-v2-guice/pom.xml b/appengine-java8/endpoints-v2-guice/pom.xml
index abc997c222e..f4a55ac8e2a 100644
--- a/appengine-java8/endpoints-v2-guice/pom.xml
+++ b/appengine-java8/endpoints-v2-guice/pom.xml
@@ -99,7 +99,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
diff --git a/appengine-java8/endpoints-v2-migration/build.gradle b/appengine-java8/endpoints-v2-migration/build.gradle
index 3ff42eddd6e..0058eef6cdb 100644
--- a/appengine-java8/endpoints-v2-migration/build.gradle
+++ b/appengine-java8/endpoints-v2-migration/build.gradle
@@ -20,7 +20,7 @@ buildscript { // Configuration for building
}
dependencies {
// App Engine Gradle plugin
- classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2'
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.3'
// Endpoints Frameworks Gradle plugin
classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:2.1.0'
diff --git a/appengine-java8/endpoints-v2-migration/pom.xml b/appengine-java8/endpoints-v2-migration/pom.xml
index 4ab47a77d67..4fdf1b61c36 100644
--- a/appengine-java8/endpoints-v2-migration/pom.xml
+++ b/appengine-java8/endpoints-v2-migration/pom.xml
@@ -68,10 +68,15 @@ limitations under the License.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
diff --git a/appengine-java8/endpoints-v2-skeleton/build.gradle b/appengine-java8/endpoints-v2-skeleton/build.gradle
index 5620dfb4a52..a85dcc35a8b 100644
--- a/appengine-java8/endpoints-v2-skeleton/build.gradle
+++ b/appengine-java8/endpoints-v2-skeleton/build.gradle
@@ -20,7 +20,7 @@ buildscript {
dependencies {
classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:2.1.0'
- classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2'
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.3'
}
}
// [END build_script]
diff --git a/appengine-java8/endpoints-v2-skeleton/pom.xml b/appengine-java8/endpoints-v2-skeleton/pom.xml
index d22847a5603..3efa3b52ce9 100644
--- a/appengine-java8/endpoints-v2-skeleton/pom.xml
+++ b/appengine-java8/endpoints-v2-skeleton/pom.xml
@@ -85,7 +85,7 @@ limitations under the License.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
diff --git a/appengine-java8/firebase-backend/pom.xml b/appengine-java8/firebase-backend/pom.xml
index 7c0e8f7335b..73d28403472 100644
--- a/appengine-java8/firebase-backend/pom.xml
+++ b/appengine-java8/firebase-backend/pom.xml
@@ -116,7 +116,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/firebase-event-proxy/pom.xml b/appengine-java8/firebase-event-proxy/pom.xml
index 5e5625d4e4a..e0383e893ff 100644
--- a/appengine-java8/firebase-event-proxy/pom.xml
+++ b/appengine-java8/firebase-event-proxy/pom.xml
@@ -95,10 +95,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/firebase-tictactoe/pom.xml b/appengine-java8/firebase-tictactoe/pom.xml
index de27b3b757f..a526a5bb72b 100644
--- a/appengine-java8/firebase-tictactoe/pom.xml
+++ b/appengine-java8/firebase-tictactoe/pom.xml
@@ -72,7 +72,7 @@
com.google.api-client
google-api-client-appengine
- 1.33.4
+ 1.34.0
@@ -118,10 +118,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/gaeinfo/pom.xml b/appengine-java8/gaeinfo/pom.xml
index fd32e8fda75..00f1417fb5b 100644
--- a/appengine-java8/gaeinfo/pom.xml
+++ b/appengine-java8/gaeinfo/pom.xml
@@ -97,7 +97,7 @@ Copyright 2017 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/guestbook-cloud-datastore/pom.xml b/appengine-java8/guestbook-cloud-datastore/pom.xml
index b3771dac67d..48ea294c768 100644
--- a/appengine-java8/guestbook-cloud-datastore/pom.xml
+++ b/appengine-java8/guestbook-cloud-datastore/pom.xml
@@ -109,10 +109,15 @@
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/helloworld/build.gradle b/appengine-java8/helloworld/build.gradle
index 724d1c98767..2e11c316436 100644
--- a/appengine-java8/helloworld/build.gradle
+++ b/appengine-java8/helloworld/build.gradle
@@ -18,7 +18,7 @@ buildscript { // Configuration for building
mavenCentral()
}
dependencies {
- classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2' // If a newer version is available, use it
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.3' // If a newer version is available, use it
}
}
diff --git a/appengine-java8/helloworld/pom.xml b/appengine-java8/helloworld/pom.xml
index 4e205977492..59bfe6b0490 100644
--- a/appengine-java8/helloworld/pom.xml
+++ b/appengine-java8/helloworld/pom.xml
@@ -87,7 +87,7 @@ limitations under the License.
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -96,10 +96,15 @@ limitations under the License.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
myProjectId
diff --git a/appengine-java8/iap/pom.xml b/appengine-java8/iap/pom.xml
index 5525362fd6c..0389b36bfd1 100644
--- a/appengine-java8/iap/pom.xml
+++ b/appengine-java8/iap/pom.xml
@@ -48,6 +48,11 @@ Copyright 2017 Google Inc.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
org.apache.maven.plugins
maven-compiler-plugin
@@ -56,7 +61,7 @@ Copyright 2017 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/images/pom.xml b/appengine-java8/images/pom.xml
index 28f47c5c7af..5648bc416a5 100644
--- a/appengine-java8/images/pom.xml
+++ b/appengine-java8/images/pom.xml
@@ -64,7 +64,7 @@ Copyright 2015 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/mail/pom.xml b/appengine-java8/mail/pom.xml
index f1901e67467..37fdb5db769 100644
--- a/appengine-java8/mail/pom.xml
+++ b/appengine-java8/mail/pom.xml
@@ -59,10 +59,15 @@ Copyright 2016 Google Inc.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/mailgun/pom.xml b/appengine-java8/mailgun/pom.xml
index 6b142ccbae6..f73552b6afb 100644
--- a/appengine-java8/mailgun/pom.xml
+++ b/appengine-java8/mailgun/pom.xml
@@ -65,10 +65,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/mailjet/pom.xml b/appengine-java8/mailjet/pom.xml
index fbd00e18fd7..f6f201a8c86 100644
--- a/appengine-java8/mailjet/pom.xml
+++ b/appengine-java8/mailjet/pom.xml
@@ -71,10 +71,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/memcache/pom.xml b/appengine-java8/memcache/pom.xml
index 2173c0efc34..42e19904cad 100644
--- a/appengine-java8/memcache/pom.xml
+++ b/appengine-java8/memcache/pom.xml
@@ -64,7 +64,7 @@ Copyright 2015 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/metadata/pom.xml b/appengine-java8/metadata/pom.xml
index b9d247f8f06..24153495676 100644
--- a/appengine-java8/metadata/pom.xml
+++ b/appengine-java8/metadata/pom.xml
@@ -92,7 +92,7 @@ Copyright 2017 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/multitenancy/pom.xml b/appengine-java8/multitenancy/pom.xml
index d6031c0c2e2..c4ce2ae33f5 100644
--- a/appengine-java8/multitenancy/pom.xml
+++ b/appengine-java8/multitenancy/pom.xml
@@ -116,10 +116,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/oauth2/pom.xml b/appengine-java8/oauth2/pom.xml
index eaf2167fbc0..72e838463e5 100644
--- a/appengine-java8/oauth2/pom.xml
+++ b/appengine-java8/oauth2/pom.xml
@@ -63,7 +63,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/pubsub/pom.xml b/appengine-java8/pubsub/pom.xml
index 1d1a7b19465..31c230b1322 100644
--- a/appengine-java8/pubsub/pom.xml
+++ b/appengine-java8/pubsub/pom.xml
@@ -81,10 +81,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
diff --git a/appengine-java8/remote-server/pom.xml b/appengine-java8/remote-server/pom.xml
index 0de916d1bc3..c0ae14d5462 100644
--- a/appengine-java8/remote-server/pom.xml
+++ b/appengine-java8/remote-server/pom.xml
@@ -60,11 +60,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
-
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/requests/pom.xml b/appengine-java8/requests/pom.xml
index c39efea3a79..a253467d482 100644
--- a/appengine-java8/requests/pom.xml
+++ b/appengine-java8/requests/pom.xml
@@ -103,7 +103,7 @@ limitations under the License.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/search/pom.xml b/appengine-java8/search/pom.xml
index 560c9595359..9676590e213 100644
--- a/appengine-java8/search/pom.xml
+++ b/appengine-java8/search/pom.xml
@@ -93,7 +93,7 @@ Copyright 2015 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/sendgrid/pom.xml b/appengine-java8/sendgrid/pom.xml
index b1086e8dc6f..e083eb17f24 100644
--- a/appengine-java8/sendgrid/pom.xml
+++ b/appengine-java8/sendgrid/pom.xml
@@ -56,10 +56,15 @@ Copyright 2018 Google LLC
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/spanner/pom.xml b/appengine-java8/spanner/pom.xml
index 19e01c23449..a0077228ea9 100644
--- a/appengine-java8/spanner/pom.xml
+++ b/appengine-java8/spanner/pom.xml
@@ -86,7 +86,11 @@
9.4.44.v20210927
-
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
org.apache.maven.plugins
3.8.1
@@ -99,7 +103,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/sparkjava-helloworld/pom.xml b/appengine-java8/sparkjava-helloworld/pom.xml
index 1ac2d9ccb02..2ec84155392 100644
--- a/appengine-java8/sparkjava-helloworld/pom.xml
+++ b/appengine-java8/sparkjava-helloworld/pom.xml
@@ -124,7 +124,7 @@ limitations under the License.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
myProjectId
diff --git a/appengine-java8/springboot-helloworld/pom.xml b/appengine-java8/springboot-helloworld/pom.xml
index fb6c574db11..1f1d724e5df 100644
--- a/appengine-java8/springboot-helloworld/pom.xml
+++ b/appengine-java8/springboot-helloworld/pom.xml
@@ -91,7 +91,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/taskqueues-deferred/pom.xml b/appengine-java8/taskqueues-deferred/pom.xml
index 90db068e976..6dc18ce4cc8 100644
--- a/appengine-java8/taskqueues-deferred/pom.xml
+++ b/appengine-java8/taskqueues-deferred/pom.xml
@@ -66,7 +66,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
com.google.appengine
@@ -87,7 +87,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/taskqueues-pull/pom.xml b/appengine-java8/taskqueues-pull/pom.xml
index 88e5e0d4a31..03c2e04ca9d 100644
--- a/appengine-java8/taskqueues-pull/pom.xml
+++ b/appengine-java8/taskqueues-pull/pom.xml
@@ -81,7 +81,7 @@ limitations under the License.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/taskqueues-push/pom.xml b/appengine-java8/taskqueues-push/pom.xml
index 3fbf64a6ef7..b58fb8a66e7 100644
--- a/appengine-java8/taskqueues-push/pom.xml
+++ b/appengine-java8/taskqueues-push/pom.xml
@@ -101,7 +101,7 @@ Copyright 2016 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/tasks/app/pom.xml b/appengine-java8/tasks/app/pom.xml
index 33c73f7bf93..fd63ab96d42 100644
--- a/appengine-java8/tasks/app/pom.xml
+++ b/appengine-java8/tasks/app/pom.xml
@@ -50,7 +50,7 @@ Copyright 2019 Google LLC
com.google.cloud
google-cloud-tasks
- 2.1.10
+ 2.1.11
@@ -80,7 +80,7 @@ Copyright 2019 Google LLC
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/tasks/quickstart/pom.xml b/appengine-java8/tasks/quickstart/pom.xml
index 1bc9b3cece7..b240e6d893d 100644
--- a/appengine-java8/tasks/quickstart/pom.xml
+++ b/appengine-java8/tasks/quickstart/pom.xml
@@ -52,7 +52,7 @@ Copyright 2018 Google LLC
com.google.cloud
google-cloud-tasks
- 2.1.10
+ 2.1.11
commons-cli
@@ -80,10 +80,15 @@ Copyright 2018 Google LLC
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/tasks/snippets/pom.xml b/appengine-java8/tasks/snippets/pom.xml
index 5e0c5d7d402..62fdef30d4f 100644
--- a/appengine-java8/tasks/snippets/pom.xml
+++ b/appengine-java8/tasks/snippets/pom.xml
@@ -18,7 +18,6 @@ Copyright 2019 Google LLC
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- war
1.0-SNAPSHOT
com.example.task
cloud-tasks-snippets
@@ -44,12 +43,12 @@ Copyright 2019 Google LLC
com.google.cloud
google-cloud-tasks
- 2.1.10
+ 2.1.11
com.google.protobuf
protobuf-java
- 3.20.0
+ 3.20.1
diff --git a/appengine-java8/translate-pubsub/pom.xml b/appengine-java8/translate-pubsub/pom.xml
index ec22e9e5fab..c167e5cd184 100644
--- a/appengine-java8/translate-pubsub/pom.xml
+++ b/appengine-java8/translate-pubsub/pom.xml
@@ -82,7 +82,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/twilio/pom.xml b/appengine-java8/twilio/pom.xml
index bff80a1032e..a6e686d7c9f 100644
--- a/appengine-java8/twilio/pom.xml
+++ b/appengine-java8/twilio/pom.xml
@@ -56,10 +56,15 @@ Copyright 2015 Google Inc.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/urlfetch/pom.xml b/appengine-java8/urlfetch/pom.xml
index dcd045edb50..cd0f2c26df6 100644
--- a/appengine-java8/urlfetch/pom.xml
+++ b/appengine-java8/urlfetch/pom.xml
@@ -55,10 +55,15 @@ Copyright 2015 Google Inc.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/appengine-java8/users/pom.xml b/appengine-java8/users/pom.xml
index 9c12dfb6197..fdf1789b75d 100644
--- a/appengine-java8/users/pom.xml
+++ b/appengine-java8/users/pom.xml
@@ -105,10 +105,15 @@ Copyright 2015 Google Inc.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/bigtable/beam/bulk-data-generator/README.md b/bigtable/beam/bulk-data-generator/README.md
index 12c1088e647..24b9d868e69 100644
--- a/bigtable/beam/bulk-data-generator/README.md
+++ b/bigtable/beam/bulk-data-generator/README.md
@@ -20,8 +20,8 @@ REGION=us-central1
3. Run the command
```
-mvn compile exec:java -Dexec.mainClass=BulkWrite \
+mvn compile exec:java -Dexec.mainClass=bigtable.BulkWrite \
"-Dexec.args=--bigtableInstanceId=$INSTANCE_ID \
--runner=dataflow --project=$GOOGLE_CLOUD_PROJECT \
--bigtableSize=$BIGTABLE_SIZE --region=$REGION"
-```
\ No newline at end of file
+```
diff --git a/bigtable/beam/bulk-data-generator/pom.xml b/bigtable/beam/bulk-data-generator/pom.xml
index c19ae8c9496..717d6cf05f8 100644
--- a/bigtable/beam/bulk-data-generator/pom.xml
+++ b/bigtable/beam/bulk-data-generator/pom.xml
@@ -26,7 +26,7 @@
8
8
- 2.37.0
+ 2.38.0
diff --git a/bigtable/beam/keyviz-art/pom.xml b/bigtable/beam/keyviz-art/pom.xml
index 90551be8628..e87239edd2a 100644
--- a/bigtable/beam/keyviz-art/pom.xml
+++ b/bigtable/beam/keyviz-art/pom.xml
@@ -37,7 +37,7 @@
UTF-8
1.8
1.8
- 2.37.0
+ 2.38.0
@@ -61,7 +61,7 @@
com.google.cloud.bigtable
bigtable-hbase-beam
- 2.1.0
+ 2.2.0
diff --git a/bigtable/beam/workload-generator/pom.xml b/bigtable/beam/workload-generator/pom.xml
index 45e984fac9f..bc0ffc3037d 100644
--- a/bigtable/beam/workload-generator/pom.xml
+++ b/bigtable/beam/workload-generator/pom.xml
@@ -26,7 +26,7 @@
8
8
- 2.37.0
+ 2.38.0
diff --git a/bigtable/memorystore/pom.xml b/bigtable/memorystore/pom.xml
index 65f86e2dd1b..36b10b71abf 100644
--- a/bigtable/memorystore/pom.xml
+++ b/bigtable/memorystore/pom.xml
@@ -44,7 +44,7 @@
com.google.cloud
google-cloud-bigtable
- 2.6.1
+ 2.6.2
diff --git a/bigtable/scheduled-backups/pom.xml b/bigtable/scheduled-backups/pom.xml
index 1918efaa6ba..190e5417a90 100644
--- a/bigtable/scheduled-backups/pom.xml
+++ b/bigtable/scheduled-backups/pom.xml
@@ -51,7 +51,7 @@ limitations under the License.
com.google.cloud
google-cloud-bigtable
- 2.6.1
+ 2.6.2
com.fasterxml.jackson.core
diff --git a/bigtable/spark/build.sbt b/bigtable/spark/build.sbt
index fff2e974c37..10a9f936ddd 100644
--- a/bigtable/spark/build.sbt
+++ b/bigtable/spark/build.sbt
@@ -22,7 +22,7 @@ version := "0.1"
// https://cloud.google.com/dataproc/docs/concepts/versioning/dataproc-release-1.4
scalaVersion := "2.11.12"
val sparkVersion = "2.4.8"
-val bigtableVersion = "2.1.0"
+val bigtableVersion = "2.2.0"
val hbaseVersion = "2.4.9"
libraryDependencies ++= Seq(
diff --git a/cloud-sql/mysql/client-side-encryption/pom.xml b/cloud-sql/mysql/client-side-encryption/pom.xml
index 2aee127445c..56bcd128fb4 100644
--- a/cloud-sql/mysql/client-side-encryption/pom.xml
+++ b/cloud-sql/mysql/client-side-encryption/pom.xml
@@ -48,7 +48,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
@@ -57,17 +57,17 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
com.google.cloud.sql
mysql-socket-factory-connector-j-8
- 1.5.0
+ 1.6.0
mysql
mysql-connector-java
- 8.0.28
+ 8.0.29
com.google.crypto.tink
diff --git a/cloud-sql/mysql/servlet/.env.yaml b/cloud-sql/mysql/servlet/.env.yaml
new file mode 100644
index 00000000000..7978d8d71b7
--- /dev/null
+++ b/cloud-sql/mysql/servlet/.env.yaml
@@ -0,0 +1,7 @@
+INSTANCE_CONNECTION_NAME: ::INSTANCE-NAME>
+INSTANCE_UNIX_SOCKET: /cloudsql/::INSTANCE-NAME>
+INSTANCE_HOST: '127.0.0.1'
+DB_PORT: 3306
+DB_USER:
+DB_PASS:
+DB_NAME:
diff --git a/cloud-sql/mysql/servlet/README.md b/cloud-sql/mysql/servlet/README.md
index 8b510b28d14..533cf1075cb 100644
--- a/cloud-sql/mysql/servlet/README.md
+++ b/cloud-sql/mysql/servlet/README.md
@@ -29,6 +29,56 @@ export DB_NAME='my_db'
Note: Saving credentials in environment variables is convenient, but not secure - consider a more
secure solution such as [Cloud KMS](https://cloud.google.com/kms/) or [Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets safe.
+## Configure SSL Certificates
+For deployments that connect directly to a Cloud SQL instance with TCP,
+without using the Cloud SQL Proxy,
+configuring SSL certificates will ensure the connection is encrypted.
+1. Use the gcloud CLI to [download the server certificate](https://cloud.google.com/sql/docs/mysql/configure-ssl-instance#server-certs) for your Cloud SQL instance.
+ - Get information about the service certificate:
+ ```
+ gcloud beta sql ssl server-ca-certs list --instance=INSTANCE_NAME
+ ```
+ - Create a server certificate:
+ ```
+ gcloud beta sql ssl server-ca-certs create --instance=INSTANCE_NAME
+ ```
+ - Download the certificate information to a local PEM file
+ ```
+ gcloud beta sql ssl server-ca-certs list \
+ --format="value(cert)" \
+ --instance=INSTANCE_NAME > \
+ server-ca.pem
+ ```
+
+1. Use the gcloud CLI to [create and download a client public key certificate and client private key](https://cloud.google.com/sql/docs/mysql/configure-ssl-instance#client-certs)
+ - Create a client certificate using the ssl client-certs create command:
+ ```
+ gcloud sql ssl client-certs create CERT_NAME client-key.pem --instance=INSTANCE_NAME
+ ```
+ - Retrieve the public key for the certificate you just created and copy it into the client-cert.pem file with the ssl client-certs describe command:
+ ```
+ gcloud sql ssl client-certs describe CERT_NAME \
+ --instance=INSTANCE_NAME \
+ --format="value(cert)" > client-cert.pem
+ ```
+1. [Import the server certificate into a custom Java truststore](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html) using `keytool`:
+ ```
+ keytool -importcert -alias MySQLCACert -file server-ca.pem \
+ -keystore -storepass
+ ```
+1. Set the `TRUST_CERT_KEYSTORE_PATH` and `TRUST_CERT_KEYSTORE_PASSWD` environment variables to the values used in the previous step.
+1. [Import the client certificate and key into a custom Java keystore](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html) using `openssl` and `keytool`:
+ - Convert the client key and certificate files to a PKCS #12 archive:
+ ```
+ openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem \
+ -name "mysqlclient" -passout pass:mypassword -out client-keystore.p12
+ ```
+ - Import the client key and certificate into a Java keystore:
+ ```
+ keytool -importkeystore -srckeystore client-keystore.p12 -srcstoretype pkcs12 \
+ -srcstorepass -destkeystore -deststoretype JKS -deststorepass
+ ```
+1. Set the `CLIENT_CERT_KEYSTORE_PATH` and `CLIENT_CERT_KEYSTORE_PASSWD` environment variables to the values used in the previous step.
## Deploying locally
To run this application locally, run the following command inside the project folder:
@@ -48,13 +98,19 @@ and verify that
has been added in your build section as a plugin.
-### Development Server
+### App Engine Development Server
The following command will run the application locally in the the GAE-development server:
```bash
mvn appengine:run
```
+### Cloud Functions Development Server
+To run the application locally as a Cloud Function, run the following command:
+```
+mvn function:run -Drun.functionTarget=com.example.cloudsql.functions.Main
+```
+
### Deploy to Google App Engine
First, update `src/main/webapp/WEB-INF/appengine-web.xml` with the correct values to pass the
@@ -120,3 +176,14 @@ mvn clean package com.google.cloud.tools:jib-maven-plugin:2.8.0:build \
For more details about using Cloud Run see http://cloud.run.
Review other [Java on Cloud Run samples](../../../run/).
+
+### Deploy to Google Cloud Functions
+
+To deploy the application to Cloud Functions, first fill in the values for required environment variables in `.env.yaml`. Then run the following command
+```
+gcloud functions deploy sql-sample \
+ --trigger-http \
+ --entry-point com.example.cloudsql.functions.Main \
+ --runtime java11 \
+ --env-vars-file .env.yaml
+```
diff --git a/cloud-sql/mysql/servlet/pom.xml b/cloud-sql/mysql/servlet/pom.xml
index cb4115eac0d..b92ed13b1cb 100644
--- a/cloud-sql/mysql/servlet/pom.xml
+++ b/cloud-sql/mysql/servlet/pom.xml
@@ -52,12 +52,12 @@
mysql
mysql-connector-java
- 8.0.28
+ 8.0.29
com.google.cloud.sql
mysql-socket-factory-connector-j-8
- 1.5.0
+ 1.6.0
com.zaxxer
@@ -77,7 +77,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -92,10 +92,27 @@
1.1.3
test
+
+
+ com.google.cloud.functions.invoker
+ java-function-invoker
+ 1.1.0
+
+
+ com.google.cloud.functions
+ functions-framework-api
+ 1.0.4
+ provided
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
org.eclipse.jetty
jetty-maven-plugin
@@ -108,12 +125,29 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
+
+
+ com.google.cloud.functions
+ function-maven-plugin
+ 0.10.0
+
+ com.example.cloudsql.functions.Main
+
+
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
index aa994574207..db3373071a0 100644
--- a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
@@ -16,11 +16,8 @@
package com.example.cloudsql;
-import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
@@ -34,101 +31,6 @@
@WebListener("Creates a connection pool that is stored in the Servlet's context for later use.")
public class ConnectionPoolContextListener implements ServletContextListener {
- // Saving credentials in environment variables is convenient, but not secure - consider a more
- // secure solution such as https://cloud.google.com/kms/ to help keep secrets safe.
- private static final String INSTANCE_CONNECTION_NAME =
- System.getenv("INSTANCE_CONNECTION_NAME");
- private static final String DB_USER = System.getenv("DB_USER");
- private static final String DB_PASS = System.getenv("DB_PASS");
- private static final String DB_NAME = System.getenv("DB_NAME");
-
- @SuppressFBWarnings(
- value = "USBR_UNNECESSARY_STORE_BEFORE_RETURN",
- justification = "Necessary for sample region tag.")
- private DataSource createConnectionPool() {
- // [START cloud_sql_mysql_servlet_create]
- // Note: For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections
- // which is preferred to using the Cloud SQL Proxy with Unix sockets.
- // See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
-
- // The configuration object specifies behaviors for the connection pool.
- HikariConfig config = new HikariConfig();
-
- // The following URL is equivalent to setting the config options below:
- // jdbc:mysql:///?cloudSqlInstance=&
- // socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=&password=
- // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
- // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
-
- // Configure which instance and what database user to connect with.
- config.setJdbcUrl(String.format("jdbc:mysql:///%s", DB_NAME));
- config.setUsername(DB_USER); // e.g. "root", "mysql"
- config.setPassword(DB_PASS); // e.g. "my-password"
-
- config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
- config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);
-
- // The ipTypes argument can be used to specify a comma delimited list of preferred IP types
- // for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
- // SocketFactory to connect with an instance's associated private IP.
- config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");
-
- // ... Specify additional connection properties here.
- // [START_EXCLUDE]
-
- // [START cloud_sql_mysql_servlet_limit]
- // maximumPoolSize limits the total number of concurrent connections this pool will keep. Ideal
- // values for this setting are highly variable on app design, infrastructure, and database.
- config.setMaximumPoolSize(5);
- // minimumIdle is the minimum number of idle connections Hikari maintains in the pool.
- // Additional connections will be established to meet this value unless the pool is full.
- config.setMinimumIdle(5);
- // [END cloud_sql_mysql_servlet_limit]
-
- // [START cloud_sql_mysql_servlet_timeout]
- // setConnectionTimeout is the maximum number of milliseconds to wait for a connection checkout.
- // Any attempt to retrieve a connection from this pool that exceeds the set limit will throw an
- // SQLException.
- config.setConnectionTimeout(10000); // 10 seconds
- // idleTimeout is the maximum amount of time a connection can sit in the pool. Connections that
- // sit idle for this many milliseconds are retried if minimumIdle is exceeded.
- config.setIdleTimeout(600000); // 10 minutes
- // [END cloud_sql_mysql_servlet_timeout]
-
- // [START cloud_sql_mysql_servlet_backoff]
- // Hikari automatically delays between failed connection attempts, eventually reaching a
- // maximum delay of `connectionTimeout / 2` between attempts.
- // [END cloud_sql_mysql_servlet_backoff]
-
- // [START cloud_sql_mysql_servlet_lifetime]
- // maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that
- // live longer than this many milliseconds will be closed and reestablished between uses. This
- // value should be several minutes shorter than the database's timeout value to avoid unexpected
- // terminations.
- config.setMaxLifetime(1800000); // 30 minutes
- // [END cloud_sql_mysql_servlet_lifetime]
-
- // [END_EXCLUDE]
-
- // Initialize the connection pool using the configuration object.
- DataSource pool = new HikariDataSource(config);
- // [END cloud_sql_mysql_servlet_create]
- return pool;
- }
-
- private void createTable(DataSource pool) throws SQLException {
- // Safely attempt to create the table schema.
- try (Connection conn = pool.getConnection()) {
- String stmt =
- "CREATE TABLE IF NOT EXISTS votes ( "
- + "vote_id SERIAL NOT NULL, time_cast timestamp NOT NULL, candidate CHAR(6) NOT NULL,"
- + " PRIMARY KEY (vote_id) );";
- try (PreparedStatement createTableStatement = conn.prepareStatement(stmt);) {
- createTableStatement.execute();
- }
- }
- }
-
@Override
public void contextDestroyed(ServletContextEvent event) {
// This function is called when the Servlet is destroyed.
@@ -145,11 +47,15 @@ public void contextInitialized(ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
DataSource pool = (DataSource) servletContext.getAttribute("my-pool");
if (pool == null) {
- pool = createConnectionPool();
+ if (System.getenv("INSTANCE_HOST") != null) {
+ pool = TcpConnectionPoolFactory.createConnectionPool();
+ } else {
+ pool = ConnectorConnectionPoolFactory.createConnectionPool();
+ }
servletContext.setAttribute("my-pool", pool);
}
try {
- createTable(pool);
+ Utils.createTable(pool);
} catch (SQLException ex) {
throw new RuntimeException(
"Unable to verify table schema. Please double check the steps"
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java
new file mode 100644
index 00000000000..a9f51330483
--- /dev/null
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import com.zaxxer.hikari.HikariConfig;
+
+public class ConnectionPoolFactory {
+
+ public static HikariConfig configureConnectionPool(HikariConfig config) {
+ // [START cloud_sql_mysql_servlet_limit]
+ // maximumPoolSize limits the total number of concurrent connections this pool will keep. Ideal
+ // values for this setting are highly variable on app design, infrastructure, and database.
+ config.setMaximumPoolSize(5);
+ // minimumIdle is the minimum number of idle connections Hikari maintains in the pool.
+ // Additional connections will be established to meet this value unless the pool is full.
+ config.setMinimumIdle(5);
+ // [END cloud_sql_mysql_servlet_limit]
+
+ // [START cloud_sql_mysql_servlet_timeout]
+ // setConnectionTimeout is the maximum number of milliseconds to wait for a connection checkout.
+ // Any attempt to retrieve a connection from this pool that exceeds the set limit will throw an
+ // SQLException.
+ config.setConnectionTimeout(10000); // 10 seconds
+ // idleTimeout is the maximum amount of time a connection can sit in the pool. Connections that
+ // sit idle for this many milliseconds are retried if minimumIdle is exceeded.
+ config.setIdleTimeout(600000); // 10 minutes
+ // [END cloud_sql_mysql_servlet_timeout]
+
+ // [START cloud_sql_mysql_servlet_backoff]
+ // Hikari automatically delays between failed connection attempts, eventually reaching a
+ // maximum delay of `connectionTimeout / 2` between attempts.
+ // [END cloud_sql_mysql_servlet_backoff]
+
+ // [START cloud_sql_mysql_servlet_lifetime]
+ // maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that
+ // live longer than this many milliseconds will be closed and reestablished between uses. This
+ // value should be several minutes shorter than the database's timeout value to avoid unexpected
+ // terminations.
+ config.setMaxLifetime(1800000); // 30 minutes
+ // [END cloud_sql_mysql_servlet_lifetime]
+ return config;
+ }
+}
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java
new file mode 100644
index 00000000000..bc34c6c06cb
--- /dev/null
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+// [START cloud_sql_mysql_servlet_connect_connector]
+// [START cloud_sql_mysql_servlet_connect_unix]
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import javax.sql.DataSource;
+
+public class ConnectorConnectionPoolFactory extends ConnectionPoolFactory {
+
+ // Note: Saving credentials in environment variables is convenient, but not
+ // secure - consider a more secure solution such as
+ // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
+ // keep secrets safe.
+ private static final String INSTANCE_CONNECTION_NAME =
+ System.getenv("INSTANCE_CONNECTION_NAME");
+ private static final String INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
+ private static final String DB_USER = System.getenv("DB_USER");
+ private static final String DB_PASS = System.getenv("DB_PASS");
+ private static final String DB_NAME = System.getenv("DB_NAME");
+
+ public static DataSource createConnectionPool() {
+ // The configuration object specifies behaviors for the connection pool.
+ HikariConfig config = new HikariConfig();
+
+ // The following URL is equivalent to setting the config options below:
+ // jdbc:mysql:///?cloudSqlInstance=&
+ // socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=&password=
+ // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
+ // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
+
+ // Configure which instance and what database user to connect with.
+ config.setJdbcUrl(String.format("jdbc:mysql:///%s", DB_NAME));
+ config.setUsername(DB_USER); // e.g. "root", "mysql"
+ config.setPassword(DB_PASS); // e.g. "my-password"
+
+ config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
+ config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);
+
+ // [END cloud_sql_mysql_servlet_connect_connector]
+ // Unix sockets are not natively supported in Java, so it is necessary to use the Cloud SQL
+ // Java Connector to connect. When setting INSTANCE_UNIX_SOCKET, the connector will
+ // call an external package that will enable Unix socket connections.
+ // Note: For Java users, the Cloud SQL Java Connector can provide authenticated connections
+ // which is usually preferable to using the Cloud SQL Proxy with Unix sockets.
+ // See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
+ if (INSTANCE_UNIX_SOCKET != null) {
+ config.addDataSourceProperty("unixSocketPath", INSTANCE_UNIX_SOCKET);
+ }
+ // [START cloud_sql_mysql_servlet_connect_connector]
+
+ // [END cloud_sql_mysql_servlet_connect_unix]
+ // The ipTypes argument can be used to specify a comma delimited list of preferred IP types
+ // for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
+ // SocketFactory to connect with an instance's associated private IP.
+ config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");
+ // [START cloud_sql_mysql_servlet_connect_unix]
+
+ // ... Specify additional connection properties here.
+ // [START_EXCLUDE]
+ configureConnectionPool(config);
+ // [END_EXCLUDE]
+
+ // Initialize the connection pool using the configuration object.
+ return new HikariDataSource(config);
+ }
+}
+// [END cloud_sql_mysql_servlet_connect_connector]
+// [END cloud_sql_mysql_servlet_connect_unix]
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
index 7f43bf811cd..6551d57e899 100644
--- a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
@@ -20,16 +20,11 @@
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
-import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.annotation.Nullable;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
@@ -38,7 +33,6 @@
import javax.sql.DataSource;
-
@SuppressFBWarnings(
value = {"SE_NO_SERIALVERSIONID", "WEM_WEAK_EXCEPTION_MESSAGING"},
justification = "Not needed for IndexServlet, Exception adds context")
@@ -47,67 +41,12 @@ public class IndexServlet extends HttpServlet {
private static final Logger LOGGER = Logger.getLogger(IndexServlet.class.getName());
- class TemplateData {
-
- public int tabCount;
- public int spaceCount;
- public List recentVotes;
-
- public TemplateData(int tabCount, int spaceCount, List recentVotes) {
- this.tabCount = tabCount;
- this.spaceCount = spaceCount;
- this.recentVotes = recentVotes;
- }
- }
-
- public TemplateData getTemplateData(DataSource pool) throws ServletException {
-
- int tabCount = 0;
- int spaceCount = 0;
- List recentVotes = new ArrayList<>();
- try (Connection conn = pool.getConnection()) {
- // PreparedStatements are compiled by the database immediately and executed at a later date.
- // Most databases cache previously compiled queries, which improves efficiency.
- String stmt1 = "SELECT candidate, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5";
- try (PreparedStatement voteStmt = conn.prepareStatement(stmt1);) {
- // Execute the statement
- ResultSet voteResults = voteStmt.executeQuery();
- // Convert a ResultSet into Vote objects
- while (voteResults.next()) {
- String candidate = voteResults.getString(1);
- Timestamp timeCast = voteResults.getTimestamp(2);
- recentVotes.add(new Vote(candidate, timeCast));
- }
- }
-
- // PreparedStatements can also be executed multiple times with different arguments. This can
- // improve efficiency, and project a query from being vulnerable to an SQL injection.
- String stmt2 = "SELECT COUNT(vote_id) FROM votes WHERE candidate=?";
- try (PreparedStatement voteCountStmt = conn.prepareStatement(stmt2);) {
- voteCountStmt.setString(1, "TABS");
- ResultSet tabResult = voteCountStmt.executeQuery();
- if (tabResult.next()) { // Move to the first result
- tabCount = tabResult.getInt(1);
- }
-
- voteCountStmt.setString(1, "SPACES");
- ResultSet spaceResult = voteCountStmt.executeQuery();
- if (spaceResult.next()) { // Move to the first result
- spaceCount = spaceResult.getInt(1);
- }
- }
+ TemplateData getTemplateData(DataSource pool) throws ServletException {
+ try {
+ return TemplateData.getTemplateData(pool);
} catch (SQLException ex) {
- // If something goes wrong, the application needs to react appropriately. This might mean
- // getting a new connection and executing the query again, or it might mean redirecting the
- // user to a different page to let them know something went wrong.
- throw new ServletException(
- "Unable to successfully connect to the database. Please check the "
- + "steps in the README and try again.",
- ex);
+ throw new ServletException(ex);
}
- TemplateData templateData = new TemplateData(tabCount, spaceCount, recentVotes);
-
- return templateData;
}
@Override
@@ -126,27 +65,13 @@ public void doGet(HttpServletRequest req, HttpServletResponse resp)
req.getRequestDispatcher("/index.jsp").forward(req, resp);
}
- // Used to validate user input. All user provided data should be validated and sanitized before
- // being used something like a SQL query. Returns null if invalid.
- @Nullable
- private String validateTeam(String input) {
- if (input != null) {
- input = input.toUpperCase(Locale.ENGLISH);
- // Must be either "TABS" or "SPACES"
- if (!"TABS".equals(input) && !"SPACES".equals(input)) {
- return null;
- }
- }
- return input;
- }
-
@SuppressFBWarnings(
value = {"SERVLET_PARAMETER", "XSS_SERVLET"},
justification = "Input is validated and sanitized.")
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// Get the team from the request and record the time of the vote.
- String team = validateTeam(req.getParameter("team"));
+ String team = Utils.validateTeam(req.getParameter("team"));
Timestamp now = new Timestamp(new Date().getTime());
if (team == null) {
resp.setStatus(400);
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java
new file mode 100644
index 00000000000..fec50bb8d8b
--- /dev/null
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+// [START cloud_sql_mysql_servlet_connect_tcp]
+// [START cloud_sql_mysql_servlet_connect_tcp_sslcerts]
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import javax.sql.DataSource;
+
+public class TcpConnectionPoolFactory extends ConnectionPoolFactory {
+
+ // Saving credentials in environment variables is convenient, but not secure - consider a more
+ // secure solution such as https://cloud.google.com/secret-manager/ to help keep secrets safe.
+ private static final String DB_USER = System.getenv("DB_USER");
+ private static final String DB_PASS = System.getenv("DB_PASS");
+ private static final String DB_NAME = System.getenv("DB_NAME");
+
+ private static final String INSTANCE_HOST = System.getenv("INSTANCE_HOST");
+ private static final String DB_PORT = System.getenv("DB_PORT");
+
+ // [END cloud_sql_mysql_servlet_connect_tcp]
+ private static final String TRUST_CERT_KEYSTORE_PATH = System.getenv(
+ "TRUST_CERT_KEYSTORE_PATH");
+ private static final String TRUST_CERT_KEYSTORE_PASSWD = System.getenv(
+ "TRUST_CERT_KEYSTORE_PASSWD");
+ private static final String CLIENT_CERT_KEYSTORE_PATH = System.getenv(
+ "CLIENT_CERT_KEYSTORE_PATH");
+ private static final String CLIENT_CERT_KEYSTORE_PASSWD = System.getenv(
+ "CLIENT_CERT_KEYSTORE_PASSWD");
+ // [START cloud_sql_mysql_servlet_connect_tcp]
+
+ public static DataSource createConnectionPool() {
+ // The configuration object specifies behaviors for the connection pool.
+ HikariConfig config = new HikariConfig();
+
+ // The following URL is equivalent to setting the config options below:
+ // jdbc:mysql://:/?user=&password=
+ // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
+ // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
+
+ // Configure which instance and what database user to connect with.
+ config.setJdbcUrl(String.format("jdbc:mysql://%s:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
+ config.setUsername(DB_USER); // e.g. "root", "mysql"
+ config.setPassword(DB_PASS); // e.g. "my-password"
+
+ // [END cloud_sql_mysql_servlet_connect_tcp]
+ // (OPTIONAL) Configure SSL certificates
+ // For deployments that connect directly to a Cloud SQL instance without
+ // using the Cloud SQL Proxy, configuring SSL certificates will ensure the
+ // connection is encrypted.
+ // See the link below for more information on how to configure SSL Certificates for use with
+ // MySQL Connector/J
+ // https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html
+ if (CLIENT_CERT_KEYSTORE_PATH != null && TRUST_CERT_KEYSTORE_PATH != null) {
+ config.addDataSourceProperty("trustCertificateKeyStoreUrl",
+ String.format("file:%s", TRUST_CERT_KEYSTORE_PATH));
+ config.addDataSourceProperty("trustCertificateKeyStorePassword", TRUST_CERT_KEYSTORE_PASSWD);
+ config.addDataSourceProperty("clientCertificateKeyStoreUrl",
+ String.format("file:%s", CLIENT_CERT_KEYSTORE_PATH));
+ config.addDataSourceProperty("clientCertificateKeyStorePassword",
+ CLIENT_CERT_KEYSTORE_PASSWD);
+ }
+ // [START cloud_sql_mysql_servlet_connect_tcp]
+
+ // ... Specify additional connection properties here.
+ // [START_EXCLUDE]
+ configureConnectionPool(config);
+ // [END_EXCLUDE]
+
+ // Initialize the connection pool using the configuration object.
+ return new HikariDataSource(config);
+ }
+}
+// [END cloud_sql_mysql_servlet_connect_tcp]
+// [END cloud_sql_mysql_servlet_connect_tcp_sslcerts]
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/TemplateData.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/TemplateData.java
new file mode 100644
index 00000000000..693da207de4
--- /dev/null
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/TemplateData.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+import javax.sql.DataSource;
+
+public class TemplateData {
+
+ public int tabCount;
+ public int spaceCount;
+ public List recentVotes;
+
+ public TemplateData(int tabCount, int spaceCount, List recentVotes) {
+ this.tabCount = tabCount;
+ this.spaceCount = spaceCount;
+ this.recentVotes = recentVotes;
+ }
+
+ public static TemplateData getTemplateData(DataSource pool) throws SQLException {
+ int tabCount = 0;
+ int spaceCount = 0;
+ List recentVotes = new ArrayList<>();
+ try (Connection conn = pool.getConnection()) {
+ // PreparedStatements are compiled by the database immediately and executed at a later date.
+ // Most databases cache previously compiled queries, which improves efficiency.
+ String stmt1 = "SELECT candidate, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5";
+ try (PreparedStatement voteStmt = conn.prepareStatement(stmt1);) {
+ // Execute the statement
+ ResultSet voteResults = voteStmt.executeQuery();
+ // Convert a ResultSet into Vote objects
+ while (voteResults.next()) {
+ String candidate = voteResults.getString(1);
+ Timestamp timeCast = voteResults.getTimestamp(2);
+ recentVotes.add(new Vote(candidate, timeCast));
+ }
+ }
+
+ // PreparedStatements can also be executed multiple times with different arguments. This can
+ // improve efficiency, and project a query from being vulnerable to an SQL injection.
+ String stmt2 = "SELECT COUNT(vote_id) FROM votes WHERE candidate=?";
+ try (PreparedStatement voteCountStmt = conn.prepareStatement(stmt2);) {
+ voteCountStmt.setString(1, "TABS");
+ ResultSet tabResult = voteCountStmt.executeQuery();
+ if (tabResult.next()) { // Move to the first result
+ tabCount = tabResult.getInt(1);
+ }
+
+ voteCountStmt.setString(1, "SPACES");
+ ResultSet spaceResult = voteCountStmt.executeQuery();
+ if (spaceResult.next()) { // Move to the first result
+ spaceCount = spaceResult.getInt(1);
+ }
+ }
+ } catch (SQLException ex) {
+ // If something goes wrong, the application needs to react appropriately. This might mean
+ // getting a new connection and executing the query again, or it might mean redirecting the
+ // user to a different page to let them know something went wrong.
+ throw new SQLException(
+ "Unable to successfully connect to the database. Please check the "
+ + "steps in the README and try again.",
+ ex);
+ }
+ TemplateData templateData = new TemplateData(tabCount, spaceCount, recentVotes);
+
+ return templateData;
+ }
+}
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/Utils.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/Utils.java
new file mode 100644
index 00000000000..a6da84573dd
--- /dev/null
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/Utils.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Locale;
+import javax.annotation.Nullable;
+import javax.sql.DataSource;
+
+public class Utils {
+
+ // Used to validate user input. All user provided data should be validated and sanitized before
+ // being used something like a SQL query. Returns null if invalid.
+ @Nullable
+ public static String validateTeam(String input) {
+ if (input != null) {
+ input = input.toUpperCase(Locale.ENGLISH);
+ // Must be either "TABS" or "SPACES"
+ if (!"TABS".equals(input) && !"SPACES".equals(input)) {
+ return null;
+ }
+ }
+ return input;
+ }
+
+ public static void createTable(DataSource pool) throws SQLException {
+ // Safely attempt to create the table schema.
+ try (Connection conn = pool.getConnection()) {
+ String stmt =
+ "CREATE TABLE IF NOT EXISTS votes ( "
+ + "vote_id SERIAL NOT NULL, time_cast timestamp NOT NULL, candidate CHAR(6) NOT NULL,"
+ + " PRIMARY KEY (vote_id) );";
+ try (PreparedStatement createTableStatement = conn.prepareStatement(stmt);) {
+ createTableStatement.execute();
+ }
+ }
+ }
+
+
+}
diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/functions/Main.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/functions/Main.java
new file mode 100644
index 00000000000..e42f4ce7128
--- /dev/null
+++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/functions/Main.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql.functions;
+
+import com.example.cloudsql.ConnectorConnectionPoolFactory;
+import com.example.cloudsql.TcpConnectionPoolFactory;
+import com.example.cloudsql.TemplateData;
+import com.example.cloudsql.Utils;
+import com.google.cloud.functions.HttpFunction;
+import com.google.cloud.functions.HttpRequest;
+import com.google.cloud.functions.HttpResponse;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+
+public class Main implements HttpFunction {
+
+ private Logger logger = Logger.getLogger(Main.class.getName());
+ private static final Gson gson = new Gson();
+
+ // Declared at cold-start, but only initialized if/when the function executes
+ // Uses the "initialization-on-demand holder" idiom
+ // More information: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
+ private static class PoolHolder {
+
+ // Making the default constructor private prohibits instantiation of this class
+ private PoolHolder() {
+ }
+
+ // This value is initialized only if (and when) the getInstance() function below is called
+ private static final DataSource INSTANCE = setupPool();
+
+ private static DataSource setupPool() {
+ DataSource pool;
+ if (System.getenv("INSTANCE_HOST") != null) {
+ pool = TcpConnectionPoolFactory.createConnectionPool();
+ } else {
+ pool = ConnectorConnectionPoolFactory.createConnectionPool();
+ }
+ try {
+ Utils.createTable(pool);
+ } catch (SQLException ex) {
+ throw new RuntimeException(
+ "Unable to verify table schema. Please double check the steps"
+ + "in the README and try again.",
+ ex);
+ }
+ return pool;
+ }
+
+ private static DataSource getInstance() {
+ return PoolHolder.INSTANCE;
+ }
+ }
+
+ private void returnVoteCounts(HttpRequest req, HttpResponse resp)
+ throws SQLException, IOException {
+ DataSource pool = PoolHolder.getInstance();
+ TemplateData templateData = TemplateData.getTemplateData(pool);
+ JsonObject respContent = new JsonObject();
+
+ // Return JSON Data
+ respContent.addProperty("tabCount", templateData.tabCount);
+ respContent.addProperty("spaceCount", templateData.spaceCount);
+ respContent.addProperty("recentVotes", gson.toJson(templateData.recentVotes));
+ resp.getWriter().write(respContent.toString());
+ resp.setStatusCode(HttpURLConnection.HTTP_OK);
+ }
+
+ private void submitVote(HttpRequest req, HttpResponse resp) throws IOException {
+ DataSource pool = PoolHolder.getInstance();
+ Timestamp now = new Timestamp(new Date().getTime());
+ JsonObject body = gson.fromJson(req.getReader(), JsonObject.class);
+ String team = Utils.validateTeam(body.get("team").getAsString());
+ if (team == null) {
+ resp.setStatusCode(400);
+ resp.getWriter().append("Invalid team specified.");
+ return;
+ }
+ try (Connection conn = pool.getConnection()) {
+ // PreparedStatements can be more efficient and project against injections.
+ String stmt = "INSERT INTO votes (time_cast, candidate) VALUES (?, ?);";
+ try (PreparedStatement voteStmt = conn.prepareStatement(stmt);) {
+ voteStmt.setTimestamp(1, now);
+ voteStmt.setString(2, team);
+
+ // Finally, execute the statement. If it fails, an error will be thrown.
+ voteStmt.execute();
+ }
+ } catch (SQLException ex) {
+ // If something goes wrong, handle the error in this section. This might involve retrying or
+ // adjusting parameters depending on the situation.
+ logger.log(Level.WARNING, "Error while attempting to submit vote.", ex);
+ resp.setStatusCode(500);
+ resp.getWriter()
+ .write(
+ "Unable to successfully cast vote! Please check the application "
+ + "logs for more details.");
+ }
+ }
+
+ @Override
+ public void service(HttpRequest req, HttpResponse resp) throws IOException, SQLException {
+
+ String method = req.getMethod();
+ switch (method) {
+ case "GET":
+ returnVoteCounts(req, resp);
+ break;
+ case "POST":
+ submitVote(req, resp);
+ break;
+ default:
+ resp.setStatusCode(HttpURLConnection.HTTP_BAD_METHOD);
+ resp.getWriter().write(String.format("HTTP Method %s is not supported", method));
+ break;
+ }
+ }
+}
diff --git a/cloud-sql/mysql/servlet/src/test/java/com/TestIndexServletMysql.java b/cloud-sql/mysql/servlet/src/test/java/com/TestIndexServletMysql.java
index abc81dfc142..57b624ba526 100644
--- a/cloud-sql/mysql/servlet/src/test/java/com/TestIndexServletMysql.java
+++ b/cloud-sql/mysql/servlet/src/test/java/com/TestIndexServletMysql.java
@@ -22,7 +22,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import com.example.cloudsql.IndexServlet.TemplateData;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.io.PrintWriter;
diff --git a/cloud-sql/postgres/client-side-encryption/pom.xml b/cloud-sql/postgres/client-side-encryption/pom.xml
index 7e57de941ea..54e4eab9f3a 100644
--- a/cloud-sql/postgres/client-side-encryption/pom.xml
+++ b/cloud-sql/postgres/client-side-encryption/pom.xml
@@ -48,7 +48,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
@@ -57,7 +57,7 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
com.google.cloud.sql
@@ -67,7 +67,7 @@
org.postgresql
postgresql
- 42.3.3
+ 42.3.5
com.google.crypto.tink
diff --git a/cloud-sql/postgres/servlet/.env.yaml b/cloud-sql/postgres/servlet/.env.yaml
new file mode 100644
index 00000000000..73e93097662
--- /dev/null
+++ b/cloud-sql/postgres/servlet/.env.yaml
@@ -0,0 +1,8 @@
+INSTANCE_CONNECTION_NAME: ::INSTANCE-NAME>
+INSTANCE_UNIX_SOCKET: /cloudsql/::INSTANCE-NAME>
+INSTANCE_HOST: '127.0.0.1'
+DB_PORT: 5432
+DB_USER:
+DB_IAM_USER:
+DB_PASS:
+DB_NAME:
diff --git a/cloud-sql/postgres/servlet/README.md b/cloud-sql/postgres/servlet/README.md
index 3c021a79125..499e0495fb4 100644
--- a/cloud-sql/postgres/servlet/README.md
+++ b/cloud-sql/postgres/servlet/README.md
@@ -27,10 +27,50 @@ export DB_PASS='my-db-pass'
export DB_NAME='my_db'
```
Note: Saving credentials in environment variables is convenient, but not secure - consider a more
-secure solution such as [Cloud KMS](https://cloud.google.com/kms/) to help keep secrets safe.
+secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets safe.
+
+## Configure SSL Certificates
+For deployments that connect directly to a Cloud SQL instance with TCP,
+without using the Cloud SQL Proxy,
+configuring SSL certificates will ensure the connection is encrypted.
+1. Use the gcloud CLI to [download the server certificate](https://cloud.google.com/sql/docs/mysql/configure-ssl-instance#server-certs) for your Cloud SQL instance.
+ - Get information about the service certificate:
+ ```
+ gcloud beta sql ssl server-ca-certs list --instance=INSTANCE_NAME
+ ```
+ - Create a server certificate:
+ ```
+ gcloud beta sql ssl server-ca-certs create --instance=INSTANCE_NAME
+ ```
+ - Download the certificate information to a local PEM file
+ ```
+ gcloud beta sql ssl server-ca-certs list \
+ --format="value(cert)" \
+ --instance=INSTANCE_NAME > \
+ server-ca.pem
+ ```
+
+2. Use the gcloud CLI to [create and download a client public key certificate and client private key](https://cloud.google.com/sql/docs/postgres/configure-ssl-instance#client-certs)
+ - Create a client certificate using the ssl client-certs create command:
+ ```
+ gcloud sql ssl client-certs create CERT_NAME client-key.pem --instance=INSTANCE_NAME
+ ```
+ - Retrieve the public key for the certificate you just created and copy it into the client-cert.pem file with the ssl client-certs describe command:
+ ```
+ gcloud sql ssl client-certs describe CERT_NAME \
+ --instance=INSTANCE_NAME \
+ --format="value(cert)" > client-cert.pem
+ ```
+3. Convert the downloaded PEM certificate and key to a PKCS12 archive using `openssl`:
+ ```
+ openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem \
+ -name "mysqlclient" -passout pass: -out client-keystore.p12
+ ```
+4. Set the `SSL_CLIENT_KEY_PATH` and `SSL_CLIENT_KEY_PASSWD` environment variables to the values from the previous step.
+The client key path should point to the PKCS12 archive file.
+6. Set the `SSL_SERVER_CA_PATH` environment variables to point to the `server-ca.pem` file downloaded earlier
## Deploying locally
-
To run this application locally, run the following command inside the project folder:
```bash
@@ -48,13 +88,19 @@ and verify that
has been added in your build section as a plugin.
-### Development Server
+### App Engine Development Server
The following command will run the application locally in the the GAE-development server:
```bash
mvn appengine:run
```
+### Cloud Functions Development Server
+To run the application locally as a Cloud Function, run the following command:
+```
+mvn function:run -Drun.functionTarget=com.example.cloudsql.functions.Main
+```
+
### Deploy to Google App Engine
First, update `src/main/webapp/WEB-INF/appengine-web.xml` with the correct values to pass the
@@ -120,3 +166,14 @@ mvn clean package com.google.cloud.tools:jib-maven-plugin:2.8.0:build \
For more details about using Cloud Run see http://cloud.run.
Review other [Java on Cloud Run samples](../../../run/).
+
+### Deploy to Google Cloud Functions
+
+To deploy the application to Cloud Functions, first fill in the values for required environment variables in `.env.yaml`. Then run the following command
+```
+gcloud functions deploy sql-sample \
+ --trigger-http \
+ --entry-point com.example.cloudsql.functions.Main \
+ --runtime java11 \
+ --env-vars-file .env.yaml
+```
diff --git a/cloud-sql/postgres/servlet/pom.xml b/cloud-sql/postgres/servlet/pom.xml
index c36d134efe7..b900ee22881 100644
--- a/cloud-sql/postgres/servlet/pom.xml
+++ b/cloud-sql/postgres/servlet/pom.xml
@@ -52,7 +52,7 @@
org.postgresql
postgresql
- 42.3.3
+ 42.3.5
com.google.cloud.sql
@@ -67,7 +67,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -82,10 +82,27 @@
1.1.3
test
+
+
+ com.google.cloud.functions.invoker
+ java-function-invoker
+ 1.0.1
+
+
+ com.google.cloud.functions
+ functions-framework-api
+ 1.0.4
+ provided
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
org.eclipse.jetty
jetty-maven-plugin
@@ -98,12 +115,27 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
-
+
+
+
+ com.google.cloud.functions
+ function-maven-plugin
+ 0.10.0
+
+ com.example.cloudsql.functions.Main
+
+
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
index f299927fab9..db3373071a0 100644
--- a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
@@ -16,11 +16,8 @@
package com.example.cloudsql;
-import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
@@ -34,102 +31,6 @@
@WebListener("Creates a connection pool that is stored in the Servlet's context for later use.")
public class ConnectionPoolContextListener implements ServletContextListener {
- // Saving credentials in environment variables is convenient, but not secure - consider a more
- // secure solution such as https://cloud.google.com/kms/ to help keep secrets safe.
- private static final String INSTANCE_CONNECTION_NAME =
- System.getenv("INSTANCE_CONNECTION_NAME");
- private static final String DB_USER = System.getenv("DB_USER");
- private static final String DB_PASS = System.getenv("DB_PASS");
- private static final String DB_NAME = System.getenv("DB_NAME");
-
- @SuppressFBWarnings(
- value = "USBR_UNNECESSARY_STORE_BEFORE_RETURN",
- justification = "Necessary for sample region tag.")
- private DataSource createConnectionPool() {
- // [START cloud_sql_postgres_servlet_create]
- // Note: For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections
- // which is preferred to using the Cloud SQL Auth Proxy with Unix sockets.
- // See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
-
- // The configuration object specifies behaviors for the connection pool.
- HikariConfig config = new HikariConfig();
-
- // The following URL is equivalent to setting the config options below:
- // jdbc:postgresql:///?cloudSqlInstance=&
- // socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=&password=
- // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
- // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
-
- // Configure which instance and what database user to connect with.
- config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));
- config.setUsername(DB_USER); // e.g. "root", "postgres"
- config.setPassword(DB_PASS); // e.g. "my-password"
-
- config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
- config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);
-
-
- // The ipTypes argument can be used to specify a comma delimited list of preferred IP types
- // for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
- // SocketFactory to connect with an instance's associated private IP.
- config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");
-
- // ... Specify additional connection properties here.
- // [START_EXCLUDE]
-
- // [START cloud_sql_postgres_servlet_limit]
- // maximumPoolSize limits the total number of concurrent connections this pool will keep. Ideal
- // values for this setting are highly variable on app design, infrastructure, and database.
- config.setMaximumPoolSize(5);
- // minimumIdle is the minimum number of idle connections Hikari maintains in the pool.
- // Additional connections will be established to meet this value unless the pool is full.
- config.setMinimumIdle(5);
- // [END cloud_sql_postgres_servlet_limit]
-
- // [START cloud_sql_postgres_servlet_timeout]
- // setConnectionTimeout is the maximum number of milliseconds to wait for a connection checkout.
- // Any attempt to retrieve a connection from this pool that exceeds the set limit will throw an
- // SQLException.
- config.setConnectionTimeout(10000); // 10 seconds
- // idleTimeout is the maximum amount of time a connection can sit in the pool. Connections that
- // sit idle for this many milliseconds are retried if minimumIdle is exceeded.
- config.setIdleTimeout(600000); // 10 minutes
- // [END cloud_sql_postgres_servlet_timeout]
-
- // [START cloud_sql_postgres_servlet_backoff]
- // Hikari automatically delays between failed connection attempts, eventually reaching a
- // maximum delay of `connectionTimeout / 2` between attempts.
- // [END cloud_sql_postgres_servlet_backoff]
-
- // [START cloud_sql_postgres_servlet_lifetime]
- // maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that
- // live longer than this many milliseconds will be closed and reestablished between uses. This
- // value should be several minutes shorter than the database's timeout value to avoid unexpected
- // terminations.
- config.setMaxLifetime(1800000); // 30 minutes
- // [END cloud_sql_postgres_servlet_lifetime]
-
- // [END_EXCLUDE]
-
- // Initialize the connection pool using the configuration object.
- DataSource pool = new HikariDataSource(config);
- // [END cloud_sql_postgres_servlet_create]
- return pool;
- }
-
- private void createTable(DataSource pool) throws SQLException {
- // Safely attempt to create the table schema.
- try (Connection conn = pool.getConnection()) {
- String stmt =
- "CREATE TABLE IF NOT EXISTS votes ( "
- + "vote_id SERIAL NOT NULL, time_cast timestamp NOT NULL, candidate CHAR(6) NOT NULL,"
- + " PRIMARY KEY (vote_id) );";
- try (PreparedStatement createTableStatement = conn.prepareStatement(stmt);) {
- createTableStatement.execute();
- }
- }
- }
-
@Override
public void contextDestroyed(ServletContextEvent event) {
// This function is called when the Servlet is destroyed.
@@ -146,11 +47,15 @@ public void contextInitialized(ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
DataSource pool = (DataSource) servletContext.getAttribute("my-pool");
if (pool == null) {
- pool = createConnectionPool();
+ if (System.getenv("INSTANCE_HOST") != null) {
+ pool = TcpConnectionPoolFactory.createConnectionPool();
+ } else {
+ pool = ConnectorConnectionPoolFactory.createConnectionPool();
+ }
servletContext.setAttribute("my-pool", pool);
}
try {
- createTable(pool);
+ Utils.createTable(pool);
} catch (SQLException ex) {
throw new RuntimeException(
"Unable to verify table schema. Please double check the steps"
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java
new file mode 100644
index 00000000000..62c45366891
--- /dev/null
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import com.zaxxer.hikari.HikariConfig;
+
+public class ConnectionPoolFactory {
+
+ public static HikariConfig configureConnectionPool(HikariConfig config) {
+ // [START cloud_sql_postgres_servlet_limit]
+ // maximumPoolSize limits the total number of concurrent connections this pool will keep. Ideal
+ // values for this setting are highly variable on app design, infrastructure, and database.
+ config.setMaximumPoolSize(5);
+ // minimumIdle is the minimum number of idle connections Hikari maintains in the pool.
+ // Additional connections will be established to meet this value unless the pool is full.
+ config.setMinimumIdle(5);
+ // [END cloud_sql_postgres_servlet_limit]
+
+ // [START cloud_sql_postgres_servlet_timeout]
+ // setConnectionTimeout is the maximum number of milliseconds to wait for a connection checkout.
+ // Any attempt to retrieve a connection from this pool that exceeds the set limit will throw an
+ // SQLException.
+ config.setConnectionTimeout(10000); // 10 seconds
+ // idleTimeout is the maximum amount of time a connection can sit in the pool. Connections that
+ // sit idle for this many milliseconds are retried if minimumIdle is exceeded.
+ config.setIdleTimeout(600000); // 10 minutes
+ // [END cloud_sql_postgres_servlet_timeout]
+
+ // [START cloud_sql_postgres_servlet_backoff]
+ // Hikari automatically delays between failed connection attempts, eventually reaching a
+ // maximum delay of `connectionTimeout / 2` between attempts.
+ // [END cloud_sql_postgres_servlet_backoff]
+
+ // [START cloud_sql_postgres_servlet_lifetime]
+ // maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that
+ // live longer than this many milliseconds will be closed and reestablished between uses. This
+ // value should be several minutes shorter than the database's timeout value to avoid unexpected
+ // terminations.
+ config.setMaxLifetime(1800000); // 30 minutes
+ // [END cloud_sql_postgres_servlet_lifetime]
+ return config;
+ }
+}
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java
new file mode 100644
index 00000000000..ca2dc179c15
--- /dev/null
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+// [START cloud_sql_postgres_servlet_connect_connector]
+// [START cloud_sql_postgres_servlet_connect_unix]
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import javax.sql.DataSource;
+
+public class ConnectorConnectionPoolFactory extends ConnectionPoolFactory {
+
+ // Note: Saving credentials in environment variables is convenient, but not
+ // secure - consider a more secure solution such as
+ // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
+ // keep secrets safe.
+ private static final String INSTANCE_CONNECTION_NAME =
+ System.getenv("INSTANCE_CONNECTION_NAME");
+ private static final String INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
+ private static final String DB_USER = System.getenv("DB_USER");
+ private static final String DB_PASS = System.getenv("DB_PASS");
+ private static final String DB_NAME = System.getenv("DB_NAME");
+
+ public static DataSource createConnectionPool() {
+ // The configuration object specifies behaviors for the connection pool.
+ HikariConfig config = new HikariConfig();
+
+ // The following URL is equivalent to setting the config options below:
+ // jdbc:postgresql:///?cloudSqlInstance=&
+ // socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=&password=
+ // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
+ // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
+
+ // Configure which instance and what database user to connect with.
+ config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));
+ config.setUsername(DB_USER); // e.g. "root", _postgres"
+ config.setPassword(DB_PASS); // e.g. "my-password"
+
+ config.addDataSourceProperty("socketFactory", "com.google.cloud.sql_postgres.SocketFactory");
+ config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);
+
+ // [END cloud_sql_postgres_servlet_connect_connector]
+ // Unix sockets are not natively supported in Java, so it is necessary to use the Cloud SQL
+ // Java Connector to connect. When setting INSTANCE_UNIX_SOCKET, the connector will
+ // call an external package that will enable Unix socket connections.
+ // Note: For Java users, the Cloud SQL Java Connector can provide authenticated connections
+ // which is usually preferable to using the Cloud SQL Proxy with Unix sockets.
+ // See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
+ if (INSTANCE_UNIX_SOCKET != null) {
+ config.addDataSourceProperty("unixSocketPath", INSTANCE_UNIX_SOCKET);
+ }
+ // [START cloud_sql_postgres_servlet_connect_connector]
+
+ // [END cloud_sql_postgres_servlet_connect_unix]
+ // The ipTypes argument can be used to specify a comma delimited list of preferred IP types
+ // for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
+ // SocketFactory to connect with an instance's associated private IP.
+ config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");
+ // [START cloud_sql_postgres_servlet_connect_unix]
+
+ // [END cloud_sql_postgres_servlet_connect_connector]
+ // [END cloud_sql_postgres_servlet_connect_unix]
+ // [START cloud_sql_postgres_servlet_auto_iam_authn]
+ // If connecting using automatic database authentication, follow the instructions for
+ // connecting using the connector, but set the DB_IAM_USER value to an IAM user or
+ // service account that has been given access to the database.
+ // See https://cloud.google.com/sql/docs/postgres/iam-logins for more details.
+ String dbIamUser = System.getenv("DB_IAM_USER");
+ if (dbIamUser != null) {
+ config.addDataSourceProperty("enableIamAuth", "true");
+ config.addDataSourceProperty("user", dbIamUser);
+ // Password must be set to a nonempty value to bypass driver validation errors.
+ config.addDataSourceProperty("password", "password");
+ // Explicitly set sslmode to disable to prevent driver from hanging.
+ // The Java Connector will handle SSL so it is unneccesary to enable it at the driver level.
+ config.addDataSourceProperty("sslmode", "disable");
+ }
+ // [END cloud_sql_postgres_servlet_auto_iam_authn]
+ // [START cloud_sql_postgres_servlet_connect_connector]
+ // [START cloud_sql_postgres_servlet_connect_unix]
+
+
+ // ... Specify additional connection properties here.
+ // [START_EXCLUDE]
+ configureConnectionPool(config);
+ // [END_EXCLUDE]
+
+ // Initialize the connection pool using the configuration object.
+ return new HikariDataSource(config);
+ }
+}
+// [END cloud_sql_postgres_servlet_connect_connector]
+// [END cloud_sql_postgres_servlet_connect_unix]
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
index 32b1eeb92dc..10e73fd094c 100644
--- a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
@@ -43,69 +43,14 @@
@WebServlet(name = "Index", value = "")
public class IndexServlet extends HttpServlet {
- class TemplateData {
-
- public int tabCount;
- public int spaceCount;
- public List recentVotes;
-
- public TemplateData(int tabCount, int spaceCount, List recentVotes) {
- this.tabCount = tabCount;
- this.spaceCount = spaceCount;
- this.recentVotes = recentVotes;
- }
- }
-
private static final Logger LOGGER = Logger.getLogger(IndexServlet.class.getName());
public TemplateData getTemplateData(DataSource pool) throws ServletException {
-
- int tabCount = 0;
- int spaceCount = 0;
- List recentVotes = new ArrayList<>();
- try (Connection conn = pool.getConnection()) {
- // PreparedStatements are compiled by the database immediately and executed at a later date.
- // Most databases cache previously compiled queries, which improves efficiency.
- String stmt1 = "SELECT candidate, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5";
- try (PreparedStatement voteStmt = conn.prepareStatement(stmt1);) {
- // Execute the statement
- ResultSet voteResults = voteStmt.executeQuery();
- // Convert a ResultSet into Vote objects
- while (voteResults.next()) {
- String candidate = voteResults.getString(1);
- Timestamp timeCast = voteResults.getTimestamp(2);
- recentVotes.add(new Vote(candidate.trim(), timeCast));
- }
- }
-
- // PreparedStatements can also be executed multiple times with different arguments. This can
- // improve efficiency, and project a query from being vulnerable to an SQL injection.
- String stmt2 = "SELECT COUNT(vote_id) FROM votes WHERE candidate=?";
- try (PreparedStatement voteCountStmt = conn.prepareStatement(stmt2);) {
- voteCountStmt.setString(1, "TABS");
- ResultSet tabResult = voteCountStmt.executeQuery();
- if (tabResult.next()) { // Move to the first result
- tabCount = tabResult.getInt(1);
- }
-
- voteCountStmt.setString(1, "SPACES");
- ResultSet spaceResult = voteCountStmt.executeQuery();
- if (spaceResult.next()) { // Move to the first result
- spaceCount = spaceResult.getInt(1);
- }
- }
+ try {
+ return TemplateData.getTemplateData(pool);
} catch (SQLException ex) {
- // If something goes wrong, the application needs to react appropriately. This might mean
- // getting a new connection and executing the query again, or it might mean redirecting the
- // user to a different page to let them know something went wrong.
- throw new ServletException(
- "Unable to successfully connect to the database. Please check the "
- + "steps in the README and try again.",
- ex);
+ throw new ServletException(ex);
}
- TemplateData templateData = new TemplateData(tabCount, spaceCount, recentVotes);
-
- return templateData;
}
@Override
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java
new file mode 100644
index 00000000000..7908f2029ff
--- /dev/null
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+// [START cloud_sql_postgres_servlet_connect_tcp]
+// [START cloud_sql_postgres_servlet_connect_tcp_sslcerts]
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import javax.sql.DataSource;
+
+public class TcpConnectionPoolFactory extends ConnectionPoolFactory {
+
+ // Note: Saving credentials in environment variables is convenient, but not
+ // secure - consider a more secure solution such as
+ // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
+ // keep secrets safe.
+ private static final String DB_USER = System.getenv("DB_USER");
+ private static final String DB_PASS = System.getenv("DB_PASS");
+ private static final String DB_NAME = System.getenv("DB_NAME");
+
+ private static final String INSTANCE_HOST = System.getenv("INSTANCE_HOST");
+ private static final String DB_PORT = System.getenv("DB_PORT");
+
+ // [END cloud_sql_postgres_servlet_connect_tcp]
+ private static final String SSL_CLIENT_KEY_PATH = System.getenv("SSL_CLIENT_KEY_PATH");
+ private static final String SSL_CLIENT_KEY_PASSWD = System.getenv("SSL_CLIENT_KEY_PASSWD");
+ private static final String SSL_SERVER_CA_PATH = System.getenv("SSL_SERVER_CA_PATH");
+ // [START cloud_sql_postgres_servlet_connect_tcp]
+
+ public static DataSource createConnectionPool() {
+ // The configuration object specifies behaviors for the connection pool.
+ HikariConfig config = new HikariConfig();
+
+ // The following URL is equivalent to setting the config options below:
+ // jdbc:postgresql://:/?user=&password=
+ // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
+ // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
+
+ // Configure which instance and what database user to connect with.
+ config.setJdbcUrl(String.format("jdbc:postgresql://%s:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
+ config.setUsername(DB_USER); // e.g. "root", "postgres"
+ config.setPassword(DB_PASS); // e.g. "my-password"
+
+ // [END cloud_sql_postgres_servlet_connect_tcp]
+ // (OPTIONAL) Configure SSL certificates
+ // For deployments that connect directly to a Cloud SQL instance without
+ // using the Cloud SQL Proxy, configuring SSL certificates will ensure the
+ // connection is encrypted.
+ // See the link below for more information on how to configure SSL Certificates for use with
+ // the Postgres JDBC driver
+ // https://jdbc.postgresql.org/documentation/head/ssl-client.html
+ if (SSL_CLIENT_KEY_PATH != null && SSL_SERVER_CA_PATH != null) {
+ config.addDataSourceProperty("ssl", "true");
+ config.addDataSourceProperty("sslmode", "verify-full");
+
+ config.addDataSourceProperty("sslkey", SSL_CLIENT_KEY_PATH);
+ config.addDataSourceProperty("sslpassword", SSL_CLIENT_KEY_PASSWD);
+ config.addDataSourceProperty("sslrootcert", SSL_SERVER_CA_PATH);
+ }
+ // [START cloud_sql_postgres_servlet_connect_tcp]
+
+ // ... Specify additional connection properties here.
+ // [START_EXCLUDE]
+ configureConnectionPool(config);
+ // [END_EXCLUDE]
+
+ // Initialize the connection pool using the configuration object.
+ return new HikariDataSource(config);
+ }
+}
+// [END cloud_sql_postgres_servlet_connect_tcp]
+// [END cloud_sql_postgres_servlet_connect_tcp_sslcerts]
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/TemplateData.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/TemplateData.java
new file mode 100644
index 00000000000..10a7f00de27
--- /dev/null
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/TemplateData.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+import javax.sql.DataSource;
+
+public class TemplateData {
+
+ public int tabCount;
+ public int spaceCount;
+ public List recentVotes;
+
+ public TemplateData(int tabCount, int spaceCount, List recentVotes) {
+ this.tabCount = tabCount;
+ this.spaceCount = spaceCount;
+ this.recentVotes = recentVotes;
+ }
+
+ public static TemplateData getTemplateData(DataSource pool) throws SQLException {
+ int tabCount = 0;
+ int spaceCount = 0;
+ List recentVotes = new ArrayList<>();
+ try (Connection conn = pool.getConnection()) {
+ // PreparedStatements are compiled by the database immediately and executed at a later date.
+ // Most databases cache previously compiled queries, which improves efficiency.
+ String stmt1 = "SELECT candidate, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5";
+ try (PreparedStatement voteStmt = conn.prepareStatement(stmt1);) {
+ // Execute the statement
+ ResultSet voteResults = voteStmt.executeQuery();
+ // Convert a ResultSet into Vote objects
+ while (voteResults.next()) {
+ String candidate = voteResults.getString(1);
+ Timestamp timeCast = voteResults.getTimestamp(2);
+ recentVotes.add(new Vote(candidate.trim(), timeCast));
+ }
+ }
+
+ // PreparedStatements can also be executed multiple times with different arguments. This can
+ // improve efficiency, and project a query from being vulnerable to an SQL injection.
+ String stmt2 = "SELECT COUNT(vote_id) FROM votes WHERE candidate=?";
+ try (PreparedStatement voteCountStmt = conn.prepareStatement(stmt2);) {
+ voteCountStmt.setString(1, "TABS");
+ ResultSet tabResult = voteCountStmt.executeQuery();
+ if (tabResult.next()) { // Move to the first result
+ tabCount = tabResult.getInt(1);
+ }
+
+ voteCountStmt.setString(1, "SPACES");
+ ResultSet spaceResult = voteCountStmt.executeQuery();
+ if (spaceResult.next()) { // Move to the first result
+ spaceCount = spaceResult.getInt(1);
+ }
+ }
+ } catch (SQLException ex) {
+ // If something goes wrong, the application needs to react appropriately. This might mean
+ // getting a new connection and executing the query again, or it might mean redirecting the
+ // user to a different page to let them know something went wrong.
+ throw new SQLException(
+ "Unable to successfully connect to the database. Please check the "
+ + "steps in the README and try again.",
+ ex);
+ }
+ TemplateData templateData = new TemplateData(tabCount, spaceCount, recentVotes);
+
+ return templateData;
+ }
+}
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/Utils.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/Utils.java
new file mode 100644
index 00000000000..0c1dcaceb41
--- /dev/null
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/Utils.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Locale;
+import javax.annotation.Nullable;
+import javax.sql.DataSource;
+
+public class Utils {
+
+ // Used to validate user input. All user provided data should be validated and sanitized before
+ // being used something like a SQL query. Returns null if invalid.
+ @Nullable
+ public static String validateTeam(String input) {
+ if (input != null) {
+ input = input.toUpperCase(Locale.ENGLISH);
+ // Must be either "TABS" or "SPACES"
+ if (!"TABS".equals(input) && !"SPACES".equals(input)) {
+ return null;
+ }
+ }
+ return input;
+ }
+
+ public static void createTable(DataSource pool) throws SQLException {
+ // Safely attempt to create the table schema.
+ try (Connection conn = pool.getConnection()) {
+ String stmt =
+ "CREATE TABLE IF NOT EXISTS votes ( "
+ + "vote_id SERIAL NOT NULL, time_cast timestamp NOT NULL, candidate CHAR(6) NOT NULL,"
+ + " PRIMARY KEY (vote_id) );";
+ try (PreparedStatement createTableStatement = conn.prepareStatement(stmt);) {
+ createTableStatement.execute();
+ }
+ }
+ }
+}
diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/functions/Main.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/functions/Main.java
new file mode 100644
index 00000000000..e42f4ce7128
--- /dev/null
+++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/functions/Main.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql.functions;
+
+import com.example.cloudsql.ConnectorConnectionPoolFactory;
+import com.example.cloudsql.TcpConnectionPoolFactory;
+import com.example.cloudsql.TemplateData;
+import com.example.cloudsql.Utils;
+import com.google.cloud.functions.HttpFunction;
+import com.google.cloud.functions.HttpRequest;
+import com.google.cloud.functions.HttpResponse;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+
+public class Main implements HttpFunction {
+
+ private Logger logger = Logger.getLogger(Main.class.getName());
+ private static final Gson gson = new Gson();
+
+ // Declared at cold-start, but only initialized if/when the function executes
+ // Uses the "initialization-on-demand holder" idiom
+ // More information: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
+ private static class PoolHolder {
+
+ // Making the default constructor private prohibits instantiation of this class
+ private PoolHolder() {
+ }
+
+ // This value is initialized only if (and when) the getInstance() function below is called
+ private static final DataSource INSTANCE = setupPool();
+
+ private static DataSource setupPool() {
+ DataSource pool;
+ if (System.getenv("INSTANCE_HOST") != null) {
+ pool = TcpConnectionPoolFactory.createConnectionPool();
+ } else {
+ pool = ConnectorConnectionPoolFactory.createConnectionPool();
+ }
+ try {
+ Utils.createTable(pool);
+ } catch (SQLException ex) {
+ throw new RuntimeException(
+ "Unable to verify table schema. Please double check the steps"
+ + "in the README and try again.",
+ ex);
+ }
+ return pool;
+ }
+
+ private static DataSource getInstance() {
+ return PoolHolder.INSTANCE;
+ }
+ }
+
+ private void returnVoteCounts(HttpRequest req, HttpResponse resp)
+ throws SQLException, IOException {
+ DataSource pool = PoolHolder.getInstance();
+ TemplateData templateData = TemplateData.getTemplateData(pool);
+ JsonObject respContent = new JsonObject();
+
+ // Return JSON Data
+ respContent.addProperty("tabCount", templateData.tabCount);
+ respContent.addProperty("spaceCount", templateData.spaceCount);
+ respContent.addProperty("recentVotes", gson.toJson(templateData.recentVotes));
+ resp.getWriter().write(respContent.toString());
+ resp.setStatusCode(HttpURLConnection.HTTP_OK);
+ }
+
+ private void submitVote(HttpRequest req, HttpResponse resp) throws IOException {
+ DataSource pool = PoolHolder.getInstance();
+ Timestamp now = new Timestamp(new Date().getTime());
+ JsonObject body = gson.fromJson(req.getReader(), JsonObject.class);
+ String team = Utils.validateTeam(body.get("team").getAsString());
+ if (team == null) {
+ resp.setStatusCode(400);
+ resp.getWriter().append("Invalid team specified.");
+ return;
+ }
+ try (Connection conn = pool.getConnection()) {
+ // PreparedStatements can be more efficient and project against injections.
+ String stmt = "INSERT INTO votes (time_cast, candidate) VALUES (?, ?);";
+ try (PreparedStatement voteStmt = conn.prepareStatement(stmt);) {
+ voteStmt.setTimestamp(1, now);
+ voteStmt.setString(2, team);
+
+ // Finally, execute the statement. If it fails, an error will be thrown.
+ voteStmt.execute();
+ }
+ } catch (SQLException ex) {
+ // If something goes wrong, handle the error in this section. This might involve retrying or
+ // adjusting parameters depending on the situation.
+ logger.log(Level.WARNING, "Error while attempting to submit vote.", ex);
+ resp.setStatusCode(500);
+ resp.getWriter()
+ .write(
+ "Unable to successfully cast vote! Please check the application "
+ + "logs for more details.");
+ }
+ }
+
+ @Override
+ public void service(HttpRequest req, HttpResponse resp) throws IOException, SQLException {
+
+ String method = req.getMethod();
+ switch (method) {
+ case "GET":
+ returnVoteCounts(req, resp);
+ break;
+ case "POST":
+ submitVote(req, resp);
+ break;
+ default:
+ resp.setStatusCode(HttpURLConnection.HTTP_BAD_METHOD);
+ resp.getWriter().write(String.format("HTTP Method %s is not supported", method));
+ break;
+ }
+ }
+}
diff --git a/cloud-sql/postgres/servlet/src/test/java/com/TestIndexServletPostgres.java b/cloud-sql/postgres/servlet/src/test/java/com/TestIndexServletPostgres.java
index d0d6c4e62c6..4cfde1336f4 100644
--- a/cloud-sql/postgres/servlet/src/test/java/com/TestIndexServletPostgres.java
+++ b/cloud-sql/postgres/servlet/src/test/java/com/TestIndexServletPostgres.java
@@ -22,7 +22,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import com.example.cloudsql.IndexServlet.TemplateData;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.io.PrintWriter;
diff --git a/cloud-sql/r2dbc/pom.xml b/cloud-sql/r2dbc/pom.xml
index 07429380ba4..5cedae050d2 100644
--- a/cloud-sql/r2dbc/pom.xml
+++ b/cloud-sql/r2dbc/pom.xml
@@ -48,7 +48,7 @@
com.google.cloud.sql
cloud-sql-connector-r2dbc-mysql
- 1.5.0
+ 1.6.0
@@ -60,7 +60,7 @@
com.google.cloud.sql
cloud-sql-connector-r2dbc-postgres
- 1.5.0
+ 1.6.0
@@ -85,7 +85,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/cloud-sql/sqlserver/client-side-encryption/pom.xml b/cloud-sql/sqlserver/client-side-encryption/pom.xml
index bf94bc91e9f..a810a155482 100644
--- a/cloud-sql/sqlserver/client-side-encryption/pom.xml
+++ b/cloud-sql/sqlserver/client-side-encryption/pom.xml
@@ -48,7 +48,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
@@ -57,17 +57,17 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
com.google.cloud.sql
cloud-sql-connector-jdbc-sqlserver
- 1.5.0
+ 1.6.0
com.microsoft.sqlserver
mssql-jdbc
- 9.4.1.jre8
+ 10.2.0.jre8
com.google.crypto.tink
diff --git a/cloud-sql/sqlserver/client-side-encryption/src/main/java/cloudsql/tink/CloudSqlConnectionPool.java b/cloud-sql/sqlserver/client-side-encryption/src/main/java/cloudsql/tink/CloudSqlConnectionPool.java
index 23eaa7c6866..a0a9438f943 100644
--- a/cloud-sql/sqlserver/client-side-encryption/src/main/java/cloudsql/tink/CloudSqlConnectionPool.java
+++ b/cloud-sql/sqlserver/client-side-encryption/src/main/java/cloudsql/tink/CloudSqlConnectionPool.java
@@ -35,6 +35,10 @@ public static DataSource createConnectionPool(String dbUser, String dbPass, Stri
config.setPassword(dbPass); // e.g. "my-password"
config.addDataSourceProperty("databaseName", dbName);
+ // The Cloud SQL Java Connector provides SSL encryption so
+ // it should be disabled at the driver level
+ config.addDataSourceProperty("encrypt", "false");
+
config.addDataSourceProperty("socketFactoryClass",
"com.google.cloud.sql.sqlserver.SocketFactory");
config.addDataSourceProperty("socketFactoryConstructorArg", instanceConnectionName);
@@ -60,4 +64,4 @@ public static void createTable(DataSource pool, String tableName) throws SQLExce
}
}
}
-// [END cloud_sql_sqlserver_cse_db]
\ No newline at end of file
+// [END cloud_sql_sqlserver_cse_db]
diff --git a/cloud-sql/sqlserver/servlet/.env.yaml b/cloud-sql/sqlserver/servlet/.env.yaml
new file mode 100644
index 00000000000..807c8b3988f
--- /dev/null
+++ b/cloud-sql/sqlserver/servlet/.env.yaml
@@ -0,0 +1,6 @@
+INSTANCE_CONNECTION_NAME: ::INSTANCE-NAME>
+INSTANCE_HOST: '127.0.0.1'
+DB_PORT: 1433
+DB_USER:
+DB_PASS:
+DB_NAME:
diff --git a/cloud-sql/sqlserver/servlet/README.md b/cloud-sql/sqlserver/servlet/README.md
index cde50bd12b4..b895b145123 100644
--- a/cloud-sql/sqlserver/servlet/README.md
+++ b/cloud-sql/sqlserver/servlet/README.md
@@ -31,6 +31,34 @@ export DB_NAME='my_db'
Note: Saving credentials in environment variables is convenient, but not secure - consider a more
secure solution such as [Cloud KMS](https://cloud.google.com/kms/) or [Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets safe.
+## Configure SSL Certificates
+For deployments that connect directly to a Cloud SQL instance with TCP,
+without using the Cloud SQL Proxy,
+configuring SSL certificates will ensure the connection is encrypted.
+1. Use the gcloud CLI to [download the server certificate](https://cloud.google.com/sql/docs/mysql/configure-ssl-instance#server-certs) for your Cloud SQL instance.
+ - Get information about the service certificate:
+ ```
+ gcloud beta sql ssl server-ca-certs list --instance=INSTANCE_NAME
+ ```
+ - Create a server certificate:
+ ```
+ gcloud beta sql ssl server-ca-certs create --instance=INSTANCE_NAME
+ ```
+ - Download the certificate information to a local PEM file
+ ```
+ gcloud beta sql ssl server-ca-certs list \
+ --format="value(cert)" \
+ --instance=INSTANCE_NAME > \
+ server-ca.pem
+ ```
+
+1. [Import the server certificate into a custom Java truststore](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html) using `keytool`:
+ ```
+ keytool -importcert -alias MySQLCACert -file server-ca.pem \
+ -keystore -storepass
+ ```
+1. Set the `TRUST_CERT_KEYSTORE_PATH` and `TRUST_CERT_KEYSTORE_PASSWD` environment variables to the values used in the previous step.
+
## Deploying locally
To run this application locally, run the following command inside the project folder:
@@ -50,7 +78,7 @@ and verify that
has been added in your build section as a plugin.
-### Development Server
+### App Engine Development Server
The following command will run the application locally in the the GAE-development server:
```bash
@@ -59,6 +87,12 @@ mvn clean package appengine:run
Note: if the GAE development server fails to start, check that you are using a supported version of Java. Supported versions are Java 8 and Java 11.
+### Cloud Functions Development Server
+To run the application locally as a Cloud Function, run the following command:
+```
+mvn function:run -Drun.functionTarget=com.example.cloudsql.functions.Main
+```
+
### Deploy to Google Cloud
First, update `src/main/webapp/WEB-INF/appengine-web.xml` with the correct values to pass the
@@ -125,5 +159,16 @@ mvn clean package com.google.cloud.tools:jib-maven-plugin:2.8.0:build \
For more details about using Cloud Run see http://cloud.run.
Review other [Java on Cloud Run samples](../../../run/).
+### Deploy to Google Cloud Functions
+
+To deploy the application to Cloud Functions, first fill in the values for required environment variables in `.env.yaml`. Then run the following command
+```
+gcloud functions deploy sql-sample \
+ --trigger-http \
+ --entry-point com.example.cloudsql.functions.Main \
+ --runtime java11 \
+ --env-vars-file .env.yaml
+```
+
### Cleanup
To avoid incurring any charges, navigate to your project's [App Engine settings](https://console.cloud.google.com/appengine/settings) and click `Disable Application`. Also [delete your Cloud SQL Instance](https://cloud.google.com/sql/docs/mysql/delete-instance) if you no longer need it.
diff --git a/cloud-sql/sqlserver/servlet/pom.xml b/cloud-sql/sqlserver/servlet/pom.xml
index c69d602fc9e..0dcb41a1304 100644
--- a/cloud-sql/sqlserver/servlet/pom.xml
+++ b/cloud-sql/sqlserver/servlet/pom.xml
@@ -52,12 +52,12 @@
com.microsoft.sqlserver
mssql-jdbc
- 9.4.1.jre8
+ 10.2.0.jre8
com.google.cloud.sql
cloud-sql-connector-jdbc-sqlserver
- 1.5.0
+ 1.6.0
com.zaxxer
@@ -67,7 +67,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -82,10 +82,27 @@
1.1.3
test
+
+
+ com.google.cloud.functions.invoker
+ java-function-invoker
+ 1.0.1
+
+
+ com.google.cloud.functions
+ functions-framework-api
+ 1.0.4
+ provided
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
org.eclipse.jetty
jetty-maven-plugin
@@ -98,7 +115,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
index cd25eb98bb2..b7f534bb2fc 100644
--- a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java
@@ -16,10 +16,7 @@
package com.example.cloudsql;
-import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Logger;
import javax.servlet.ServletContextEvent;
@@ -40,94 +37,6 @@ public class ConnectionPoolContextListener implements ServletContextListener {
private static final String DB_PASS = System.getenv("DB_PASS");
private static final String DB_NAME = System.getenv("DB_NAME");
- private DataSource createConnectionPool() {
- // [START cloud_sql_sqlserver_servlet_create]
- // Note: For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections
- // which is preferred to using the Cloud SQL Proxy with Unix sockets.
- // See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
-
- // The configuration object specifies behaviors for the connection pool.
- HikariConfig config = new HikariConfig();
-
- // The following is equivalent to setting the config options below:
- // jdbc:sqlserver://;user=;password=;databaseName=;
- // socketFactoryClass=com.google.cloud.sql.sqlserver.SocketFactory;
- // socketFactoryConstructorArg=
-
- // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
- // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
-
- // Configure which instance and what database user to connect with.
- config
- .setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");
- config.setUsername(DB_USER); // e.g. "root", "sqlserver"
- config.setPassword(DB_PASS); // e.g. "my-password"
- config.addDataSourceProperty("databaseName", DB_NAME);
-
- config.addDataSourceProperty("socketFactoryClass",
- "com.google.cloud.sql.sqlserver.SocketFactory");
- config.addDataSourceProperty("socketFactoryConstructorArg", INSTANCE_CONNECTION_NAME);
-
- // ... Specify additional connection properties here.
-
- // [START_EXCLUDE]
-
- // [START cloud_sql_sqlserver_servlet_limit]
- // maximumPoolSize limits the total number of concurrent connections this pool will keep. Ideal
- // values for this setting are highly variable on app design, infrastructure, and database.
- config.setMaximumPoolSize(5);
- // minimumIdle is the minimum number of idle connections Hikari maintains in the pool.
- // Additional connections will be established to meet this value unless the pool is full.
- config.setMinimumIdle(5);
- // [END cloud_sql_sqlserver_servlet_limit]
-
- // [START cloud_sql_sqlserver_servlet_timeout]
- // setConnectionTimeout is the maximum number of milliseconds to wait for a connection checkout.
- // Any attempt to retrieve a connection from this pool that exceeds the set limit will throw an
- // SQLException.
- config.setConnectionTimeout(10000); // 10 seconds
- // idleTimeout is the maximum amount of time a connection can sit in the pool. Connections that
- // sit idle for this many milliseconds are retried if minimumIdle is exceeded.
- config.setIdleTimeout(600000); // 10 minutes
- // [END cloud_sql_sqlserver_servlet_timeout]
-
- // [START cloud_sql_sqlserver_servlet_backoff]
- // Hikari automatically delays between failed connection attempts, eventually reaching a
- // maximum delay of `connectionTimeout / 2` between attempts.
- // [END cloud_sql_sqlserver_servlet_backoff]
-
- // [START cloud_sql_sqlserver_servlet_lifetime]
- // maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that
- // live longer than this many milliseconds will be closed and reestablished between uses. This
- // value should be several minutes shorter than the database's timeout value to avoid unexpected
- // terminations.
- config.setMaxLifetime(1800000); // 30 minutes
- // [END cloud_sql_sqlserver_servlet_lifetime]
-
- // [END_EXCLUDE]
-
- // Initialize the connection pool using the configuration object.
- DataSource pool = new HikariDataSource(config);
- // [END cloud_sql_sqlserver_servlet_create]
- return pool;
- }
-
- private void createTable(DataSource pool) throws SQLException {
- // Safely attempt to create the table schema.
- try (Connection conn = pool.getConnection()) {
- PreparedStatement createTableStatement = conn.prepareStatement(
- "IF NOT EXISTS ("
- + "SELECT * FROM sysobjects WHERE name='votes' and xtype='U')"
- + "CREATE TABLE votes ("
- + "vote_id INT NOT NULL IDENTITY,"
- + "time_cast DATETIME NOT NULL,"
- + "candidate VARCHAR(6) NOT NULL,"
- + "PRIMARY KEY (vote_id));"
- );
- createTableStatement.execute();
- }
- }
-
@Override
public void contextDestroyed(ServletContextEvent event) {
// This function is called when the Servlet is destroyed.
@@ -143,11 +52,16 @@ public void contextInitialized(ServletContextEvent event) {
// that can be used to connect to.
DataSource pool = (DataSource) event.getServletContext().getAttribute("my-pool");
if (pool == null) {
- pool = createConnectionPool();
+ if (System.getenv("INSTANCE_HOST") != null) {
+ pool = TcpConnectionPoolFactory.createConnectionPool();
+ } else {
+ pool = ConnectorConnectionPoolFactory.createConnectionPool();
+ }
event.getServletContext().setAttribute("my-pool", pool);
}
try {
- createTable(pool);
+ // from src/main/java/com/example/cloudsql/Utils.java
+ Utils.createTable(pool);
} catch (SQLException ex) {
throw new RuntimeException("Unable to verify table schema. Please double check the steps"
+ "in the README and try again.", ex);
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java
new file mode 100644
index 00000000000..e35b731771d
--- /dev/null
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectionPoolFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import com.zaxxer.hikari.HikariConfig;
+
+public class ConnectionPoolFactory {
+
+ public static HikariConfig configureConnectionPool(HikariConfig config) {
+ // [START cloud_sql_sqlserver_servlet_limit]
+ // maximumPoolSize limits the total number of concurrent connections this pool will keep. Ideal
+ // values for this setting are highly variable on app design, infrastructure, and database.
+ config.setMaximumPoolSize(5);
+ // minimumIdle is the minimum number of idle connections Hikari maintains in the pool.
+ // Additional connections will be established to meet this value unless the pool is full.
+ config.setMinimumIdle(5);
+ // [END cloud_sql_sqlserver_servlet_limit]
+
+ // [START cloud_sql_sqlserver_servlet_timeout]
+ // setConnectionTimeout is the maximum number of milliseconds to wait for a connection checkout.
+ // Any attempt to retrieve a connection from this pool that exceeds the set limit will throw an
+ // SQLException.
+ config.setConnectionTimeout(10000); // 10 seconds
+ // idleTimeout is the maximum amount of time a connection can sit in the pool. Connections that
+ // sit idle for this many milliseconds are retried if minimumIdle is exceeded.
+ config.setIdleTimeout(600000); // 10 minutes
+ // [END cloud_sql_sqlserver_servlet_timeout]
+
+ // [START cloud_sql_sqlserver_servlet_backoff]
+ // Hikari automatically delays between failed connection attempts, eventually reaching a
+ // maximum delay of `connectionTimeout / 2` between attempts.
+ // [END cloud_sql_sqlserver_servlet_backoff]
+
+ // [START cloud_sql_sqlserver_servlet_lifetime]
+ // maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that
+ // live longer than this many milliseconds will be closed and reestablished between uses. This
+ // value should be several minutes shorter than the database's timeout value to avoid unexpected
+ // terminations.
+ config.setMaxLifetime(1800000); // 30 minutes
+ // [END cloud_sql_sqlserver_servlet_lifetime]
+ return config;
+ }
+}
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java
new file mode 100644
index 00000000000..b4d738cd846
--- /dev/null
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/ConnectorConnectionPoolFactory.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+// [START cloud_sql_sqlserver_servlet_connect_connector]
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import javax.sql.DataSource;
+
+public class ConnectorConnectionPoolFactory extends ConnectionPoolFactory {
+
+ // Note: Saving credentials in environment variables is convenient, but not
+ // secure - consider a more secure solution such as
+ // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
+ // keep secrets safe.
+ private static final String INSTANCE_CONNECTION_NAME =
+ System.getenv("INSTANCE_CONNECTION_NAME");
+ private static final String DB_USER = System.getenv("DB_USER");
+ private static final String DB_PASS = System.getenv("DB_PASS");
+ private static final String DB_NAME = System.getenv("DB_NAME");
+
+ public static DataSource createConnectionPool() {
+ // The configuration object specifies behaviors for the connection pool.
+ HikariConfig config = new HikariConfig();
+
+ // The following is equivalent to setting the config options below:
+ // jdbc:sqlserver://;user=;password=;databaseName=;
+ // socketFactoryClass=com.google.cloud.sql.sqlserver.SocketFactory;
+ // socketFactoryConstructorArg=
+
+ // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
+ // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url
+
+ // Configure which instance and what database user to connect with.
+ config
+ .setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");
+ config.setUsername(DB_USER); // e.g. "root", "sqlserver"
+ config.setPassword(DB_PASS); // e.g. "my-password"
+ config.addDataSourceProperty("databaseName", DB_NAME);
+
+ config.addDataSourceProperty("socketFactoryClass",
+ "com.google.cloud.sql.sqlserver.SocketFactory");
+ config.addDataSourceProperty("socketFactoryConstructorArg", INSTANCE_CONNECTION_NAME);
+
+ // The Java Connector provides SSL encryption, so it should be disabled
+ // at the driver level.
+ config.addDataSourceProperty("encrypt", "false");
+
+ // ... Specify additional connection properties here.
+ // [START_EXCLUDE]
+ configureConnectionPool(config);
+ // [END_EXCLUDE]
+
+ // Initialize the connection pool using the configuration object.
+ return new HikariDataSource(config);
+ }
+}
+// [END cloud_sql_sqlserver_servlet_connect_connector]
+
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
index 425d358f132..60aa1ba8621 100644
--- a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java
@@ -19,12 +19,9 @@
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
@@ -35,71 +32,17 @@
import javax.sql.DataSource;
-
@WebServlet(name = "Index", value = "")
public class IndexServlet extends HttpServlet {
private static final Logger LOGGER = Logger.getLogger(IndexServlet.class.getName());
- class TemplateData {
-
- public int tabCount;
- public int spaceCount;
- public List recentVotes;
-
- public TemplateData(int tabCount, int spaceCount, List recentVotes) {
- this.tabCount = tabCount;
- this.spaceCount = spaceCount;
- this.recentVotes = recentVotes;
- }
- }
-
public TemplateData getTemplateData(DataSource pool) throws ServletException {
-
- int tabCount;
- int spaceCount;
- List recentVotes = new ArrayList<>();
- try (Connection conn = pool.getConnection()) {
- // PreparedStatements are compiled by the database immediately and executed at a later date.
- // Most databases cache previously compiled queries, which improves efficiency.
- PreparedStatement voteStmt = conn.prepareStatement(
- "SELECT TOP(5) candidate, time_cast FROM votes ORDER BY time_cast DESC");
- // Execute the statement
- ResultSet voteResults = voteStmt.executeQuery();
- // Convert a ResultSet into Vote objects
- while (voteResults.next()) {
- String candidate = voteResults.getString(1);
- Timestamp timeCast = voteResults.getTimestamp(2);
- Vote vote = new Vote(candidate.trim(), timeCast);
- recentVotes.add(vote);
- }
-
- // PreparedStatements can also be executed multiple times with different arguments. This can
- // improve efficiency, and project a query from being vulnerable to an SQL injection.
- PreparedStatement voteCountStmt = conn.prepareStatement(
- "SELECT COUNT(vote_id) FROM votes WHERE candidate=?");
-
- voteCountStmt.setString(1, "TABS");
- ResultSet tabResult = voteCountStmt.executeQuery();
- tabResult.next(); // Move to the first result
- tabCount = tabResult.getInt(1);
-
- voteCountStmt.setString(1, "SPACES");
- ResultSet spaceResult = voteCountStmt.executeQuery();
- spaceResult.next(); // Move to the first result
- spaceCount = spaceResult.getInt(1);
-
+ try {
+ return TemplateData.getTemplateData(pool);
} catch (SQLException ex) {
- // If something goes wrong, the application needs to react appropriately. This might mean
- // getting a new connection and executing the query again, or it might mean redirecting the
- // user to a different page to let them know something went wrong.
- throw new ServletException("Unable to successfully connect to the database. Please check the "
- + "steps in the README and try again.", ex);
+ throw new ServletException(ex);
}
-
- TemplateData templateData = new TemplateData(tabCount, spaceCount, recentVotes);
-
- return templateData;
}
@Override
@@ -122,12 +65,9 @@ public void doGet(HttpServletRequest req, HttpServletResponse resp)
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
// Get the team from the request and record the time of the vote.
- String team = req.getParameter("team");
- if (team != null) {
- team = team.toUpperCase();
- }
+ String team = Utils.validateTeam(req.getParameter("team"));
Timestamp now = new Timestamp(new Date().getTime());
- if (team == null || (!team.equals("TABS") && !team.equals("SPACES"))) {
+ if (team == null) {
resp.setStatus(400);
resp.getWriter().append("Invalid team specified.");
return;
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java
new file mode 100644
index 00000000000..97f64d02286
--- /dev/null
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/TcpConnectionPoolFactory.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+// [START cloud_sql_sqlserver_servlet_connect_tcp]
+// [START cloud_sql_sqlserver_servlet_connect_tcp_sslcerts]
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import javax.sql.DataSource;
+
+public class TcpConnectionPoolFactory extends ConnectionPoolFactory {
+
+ // Note: Saving credentials in environment variables is convenient, but not
+ // secure - consider a more secure solution such as
+ // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
+ // keep secrets safe.
+ private static final String DB_USER = System.getenv("DB_USER");
+ private static final String DB_PASS = System.getenv("DB_PASS");
+ private static final String DB_NAME = System.getenv("DB_NAME");
+
+ private static final String INSTANCE_HOST = System.getenv("INSTANCE_HOST");
+ private static final String DB_PORT = System.getenv("DB_PORT");
+
+ // [END cloud_sql_sqlserver_servlet_connect_tcp]
+ private static final String TRUST_CERT_KEYSTORE_PATH = System.getenv(
+ "TRUST_CERT_KEYSTORE_NAME");
+ private static final String TRUST_CERT_KEYSTORE_PASSWD = System.getenv(
+ "TRUST_CERT_KEYSTORE_PASSWD");
+ // [START cloud_sql_sqlserver_servlet_connect_tcp]
+
+ public static DataSource createConnectionPool() {
+ // The configuration object specifies behaviors for the connection pool.
+ HikariConfig config = new HikariConfig();
+
+ // Configure which instance and what database user to connect with.
+ config.setJdbcUrl(
+ String.format("jdbc:sqlserver://%s:%s;databaseName=%s", INSTANCE_HOST, DB_PORT, DB_NAME));
+ config.setUsername(DB_USER); // e.g. "root", "sqlserver"
+ config.setPassword(DB_PASS); // e.g. "my-password"
+
+ // [END cloud_sql_sqlserver_servlet_connect_tcp]
+ // (OPTIONAL) Configure SSL certificates
+ // For deployments that connect directly to a Cloud SQL instance without
+ // using the Cloud SQL Proxy, configuring SSL certificates will ensure the
+ // connection is encrypted.
+ // For details about how the SQL Server JDBC driver handles SSL encryption, see the link below
+ // https://docs.microsoft.com/en-us/sql/connect/jdbc/understanding-ssl-support?view=sql-server-ver15
+
+ if (TRUST_CERT_KEYSTORE_PATH != null) {
+ config.addDataSourceProperty("encrypt", "true");
+ config.addDataSourceProperty("trustStore", TRUST_CERT_KEYSTORE_PATH);
+ config.addDataSourceProperty("trustStorePassword", TRUST_CERT_KEYSTORE_PASSWD);
+ }
+ // [START cloud_sql_sqlserver_servlet_connect_tcp]
+
+ // ... Specify additional connection properties here.
+ // [START_EXCLUDE]
+ configureConnectionPool(config);
+ // [END_EXCLUDE]
+
+ // Initialize the connection pool using the configuration object.
+ return new HikariDataSource(config);
+ }
+}
+// [END cloud_sql_sqlserver_servlet_connect_tcp]
+// [END cloud_sql_sqlserver_servlet_connect_tcp_sslcerts]
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/TemplateData.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/TemplateData.java
new file mode 100644
index 00000000000..c2cb79e0a3d
--- /dev/null
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/TemplateData.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+import javax.sql.DataSource;
+
+public class TemplateData {
+
+ public int tabCount;
+ public int spaceCount;
+ public List recentVotes;
+
+ public TemplateData(int tabCount, int spaceCount, List recentVotes) {
+ this.tabCount = tabCount;
+ this.spaceCount = spaceCount;
+ this.recentVotes = recentVotes;
+ }
+
+ public static TemplateData getTemplateData(DataSource pool) throws SQLException {
+ int tabCount;
+ int spaceCount;
+ List recentVotes = new ArrayList<>();
+ try (Connection conn = pool.getConnection()) {
+ // PreparedStatements are compiled by the database immediately and executed at a later date.
+ // Most databases cache previously compiled queries, which improves efficiency.
+ PreparedStatement voteStmt = conn.prepareStatement(
+ "SELECT TOP(5) candidate, time_cast FROM votes ORDER BY time_cast DESC");
+ // Execute the statement
+ ResultSet voteResults = voteStmt.executeQuery();
+ // Convert a ResultSet into Vote objects
+ while (voteResults.next()) {
+ String candidate = voteResults.getString(1);
+ Timestamp timeCast = voteResults.getTimestamp(2);
+ Vote vote = new Vote(candidate.trim(), timeCast);
+ recentVotes.add(vote);
+ }
+
+ // PreparedStatements can also be executed multiple times with different arguments. This can
+ // improve efficiency, and project a query from being vulnerable to an SQL injection.
+ PreparedStatement voteCountStmt = conn.prepareStatement(
+ "SELECT COUNT(vote_id) FROM votes WHERE candidate=?");
+
+ voteCountStmt.setString(1, "TABS");
+ ResultSet tabResult = voteCountStmt.executeQuery();
+ tabResult.next(); // Move to the first result
+ tabCount = tabResult.getInt(1);
+
+ voteCountStmt.setString(1, "SPACES");
+ ResultSet spaceResult = voteCountStmt.executeQuery();
+ spaceResult.next(); // Move to the first result
+ spaceCount = spaceResult.getInt(1);
+
+ } catch (SQLException ex) {
+ // If something goes wrong, the application needs to react appropriately. This might mean
+ // getting a new connection and executing the query again, or it might mean redirecting the
+ // user to a different page to let them know something went wrong.
+ throw new SQLException("Unable to successfully connect to the database. Please check the "
+ + "steps in the README and try again.", ex);
+ }
+
+ return new TemplateData(tabCount, spaceCount, recentVotes);
+ }
+}
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/Utils.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/Utils.java
new file mode 100644
index 00000000000..08b6425982e
--- /dev/null
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/Utils.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Locale;
+import javax.annotation.Nullable;
+import javax.sql.DataSource;
+
+public class Utils {
+
+ // Used to validate user input. All user provided data should be validated and sanitized before
+ // being used something like a SQL query. Returns null if invalid.
+ @Nullable
+ public static String validateTeam(String input) {
+ if (input != null) {
+ input = input.toUpperCase(Locale.ENGLISH);
+ // Must be either "TABS" or "SPACES"
+ if (!"TABS".equals(input) && !"SPACES".equals(input)) {
+ return null;
+ }
+ }
+ return input;
+ }
+
+ public static void createTable(DataSource pool) throws SQLException {
+ // Safely attempt to create the table schema.
+ try (Connection conn = pool.getConnection()) {
+ PreparedStatement createTableStatement = conn.prepareStatement(
+ "IF NOT EXISTS ("
+ + "SELECT * FROM sysobjects WHERE name='votes' and xtype='U')"
+ + "CREATE TABLE votes ("
+ + "vote_id INT NOT NULL IDENTITY,"
+ + "time_cast DATETIME NOT NULL,"
+ + "candidate VARCHAR(6) NOT NULL,"
+ + "PRIMARY KEY (vote_id));"
+ );
+ createTableStatement.execute();
+ }
+ }
+
+
+}
diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/functions/Main.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/functions/Main.java
new file mode 100644
index 00000000000..e42f4ce7128
--- /dev/null
+++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/functions/Main.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.cloudsql.functions;
+
+import com.example.cloudsql.ConnectorConnectionPoolFactory;
+import com.example.cloudsql.TcpConnectionPoolFactory;
+import com.example.cloudsql.TemplateData;
+import com.example.cloudsql.Utils;
+import com.google.cloud.functions.HttpFunction;
+import com.google.cloud.functions.HttpRequest;
+import com.google.cloud.functions.HttpResponse;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+
+public class Main implements HttpFunction {
+
+ private Logger logger = Logger.getLogger(Main.class.getName());
+ private static final Gson gson = new Gson();
+
+ // Declared at cold-start, but only initialized if/when the function executes
+ // Uses the "initialization-on-demand holder" idiom
+ // More information: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
+ private static class PoolHolder {
+
+ // Making the default constructor private prohibits instantiation of this class
+ private PoolHolder() {
+ }
+
+ // This value is initialized only if (and when) the getInstance() function below is called
+ private static final DataSource INSTANCE = setupPool();
+
+ private static DataSource setupPool() {
+ DataSource pool;
+ if (System.getenv("INSTANCE_HOST") != null) {
+ pool = TcpConnectionPoolFactory.createConnectionPool();
+ } else {
+ pool = ConnectorConnectionPoolFactory.createConnectionPool();
+ }
+ try {
+ Utils.createTable(pool);
+ } catch (SQLException ex) {
+ throw new RuntimeException(
+ "Unable to verify table schema. Please double check the steps"
+ + "in the README and try again.",
+ ex);
+ }
+ return pool;
+ }
+
+ private static DataSource getInstance() {
+ return PoolHolder.INSTANCE;
+ }
+ }
+
+ private void returnVoteCounts(HttpRequest req, HttpResponse resp)
+ throws SQLException, IOException {
+ DataSource pool = PoolHolder.getInstance();
+ TemplateData templateData = TemplateData.getTemplateData(pool);
+ JsonObject respContent = new JsonObject();
+
+ // Return JSON Data
+ respContent.addProperty("tabCount", templateData.tabCount);
+ respContent.addProperty("spaceCount", templateData.spaceCount);
+ respContent.addProperty("recentVotes", gson.toJson(templateData.recentVotes));
+ resp.getWriter().write(respContent.toString());
+ resp.setStatusCode(HttpURLConnection.HTTP_OK);
+ }
+
+ private void submitVote(HttpRequest req, HttpResponse resp) throws IOException {
+ DataSource pool = PoolHolder.getInstance();
+ Timestamp now = new Timestamp(new Date().getTime());
+ JsonObject body = gson.fromJson(req.getReader(), JsonObject.class);
+ String team = Utils.validateTeam(body.get("team").getAsString());
+ if (team == null) {
+ resp.setStatusCode(400);
+ resp.getWriter().append("Invalid team specified.");
+ return;
+ }
+ try (Connection conn = pool.getConnection()) {
+ // PreparedStatements can be more efficient and project against injections.
+ String stmt = "INSERT INTO votes (time_cast, candidate) VALUES (?, ?);";
+ try (PreparedStatement voteStmt = conn.prepareStatement(stmt);) {
+ voteStmt.setTimestamp(1, now);
+ voteStmt.setString(2, team);
+
+ // Finally, execute the statement. If it fails, an error will be thrown.
+ voteStmt.execute();
+ }
+ } catch (SQLException ex) {
+ // If something goes wrong, handle the error in this section. This might involve retrying or
+ // adjusting parameters depending on the situation.
+ logger.log(Level.WARNING, "Error while attempting to submit vote.", ex);
+ resp.setStatusCode(500);
+ resp.getWriter()
+ .write(
+ "Unable to successfully cast vote! Please check the application "
+ + "logs for more details.");
+ }
+ }
+
+ @Override
+ public void service(HttpRequest req, HttpResponse resp) throws IOException, SQLException {
+
+ String method = req.getMethod();
+ switch (method) {
+ case "GET":
+ returnVoteCounts(req, resp);
+ break;
+ case "POST":
+ submitVote(req, resp);
+ break;
+ default:
+ resp.setStatusCode(HttpURLConnection.HTTP_BAD_METHOD);
+ resp.getWriter().write(String.format("HTTP Method %s is not supported", method));
+ break;
+ }
+ }
+}
diff --git a/cloud-sql/sqlserver/servlet/src/test/java/com/TestIndexServletSqlServer.java b/cloud-sql/sqlserver/servlet/src/test/java/com/TestIndexServletSqlServer.java
index b6c930d71bf..c73d91ba42a 100644
--- a/cloud-sql/sqlserver/servlet/src/test/java/com/TestIndexServletSqlServer.java
+++ b/cloud-sql/sqlserver/servlet/src/test/java/com/TestIndexServletSqlServer.java
@@ -22,7 +22,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import com.example.cloudsql.IndexServlet.TemplateData;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.io.PrintWriter;
@@ -94,6 +93,7 @@ public static void createPool() throws SQLException {
"com.google.cloud.sql.sqlserver.SocketFactory");
config.addDataSourceProperty("socketFactoryConstructorArg",
System.getenv("SQLSERVER_CONNECTION_NAME"));
+ config.addDataSourceProperty("encrypt", "false");
pool = new HikariDataSource(config);
createTable(pool);
@@ -138,4 +138,4 @@ public void testServletPost() throws Exception {
writer.flush();
assertTrue(stringWriter.toString().contains("Vote successfully cast for"));
}
-}
\ No newline at end of file
+}
diff --git a/compute/cloud-client/pom.xml b/compute/cloud-client/pom.xml
index 93922c625be..511e6201519 100644
--- a/compute/cloud-client/pom.xml
+++ b/compute/cloud-client/pom.xml
@@ -23,7 +23,7 @@
google-cloud-compute
com.google.cloud
- 1.7.0
+ 1.8.1
google-cloud-storage
@@ -37,7 +37,7 @@
com.google.api
gax-httpjson
- 0.100.0
+ 0.99.0
@@ -54,6 +54,25 @@
test
4.13.2
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.8.2
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.8.2
+ test
+
@@ -65,6 +84,18 @@
pom
25.0.0
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M6
+ maven-plugin
+
+
+ **/*IT.java
+
+
+
@@ -88,4 +119,33 @@
1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M6
+
+
+ all
+ true
+ 10C
+ true
+
+ **/*IT.java
+
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 3.0.0-M6
+
+ true
+
+
+
+
+
diff --git a/compute/cloud-client/src/main/java/compute/CreateEncryptedInstance.java b/compute/cloud-client/src/main/java/compute/CreateEncryptedInstance.java
index c1a36efa86b..8829834adbc 100644
--- a/compute/cloud-client/src/main/java/compute/CreateEncryptedInstance.java
+++ b/compute/cloud-client/src/main/java/compute/CreateEncryptedInstance.java
@@ -30,11 +30,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateEncryptedInstance {
public static void main(String[] args)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
String project = "your-project-id";
String zone = "zone-name";
@@ -48,7 +50,7 @@ public static void main(String[] args)
// in the specified project and zone.
public static void createEncryptedInstance(String project, String zone, String instanceName,
String diskEncryptionKey)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
/* Below are sample values that can be replaced.
machineType: machine type of the VM being created.
(This value uses the format zones/{zone}/machineTypes/{type_name}.
@@ -111,7 +113,7 @@ public static void createEncryptedInstance(String project, String zone, String i
instancesClient.insertAsync(insertInstanceRequest);
// Wait for the operation to complete.
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance creation failed ! ! " + response);
diff --git a/compute/cloud-client/src/main/java/compute/CreateFirewallRule.java b/compute/cloud-client/src/main/java/compute/CreateFirewallRule.java
index dff25241c83..61a72e8ad10 100644
--- a/compute/cloud-client/src/main/java/compute/CreateFirewallRule.java
+++ b/compute/cloud-client/src/main/java/compute/CreateFirewallRule.java
@@ -26,11 +26,13 @@
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateFirewallRule {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample
/* project: project ID or project number of the Cloud project you want to use.
firewallRuleName: name of the rule that is created.
@@ -49,7 +51,7 @@ public static void main(String[] args)
// Creates a simple firewall rule allowing for incoming HTTP and
// HTTPS access from the entire Internet.
public static void createFirewall(String project, String firewallRuleName, String network)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* Initialize client that will be used to send requests. This client only needs to be created
once, and can be reused for multiple requests. After completing all of your requests, call
the `firewallsClient.close()` method on the client to safely
@@ -78,7 +80,7 @@ public static void createFirewall(String project, String firewallRuleName, Strin
.setFirewallResource(firewallRule)
.setProject(project).build();
- firewallsClient.insertAsync(insertFirewallRequest).get();
+ firewallsClient.insertAsync(insertFirewallRequest).get(3, TimeUnit.MINUTES);
System.out.println("Firewall rule created successfully -> " + firewallRuleName);
}
diff --git a/compute/cloud-client/src/main/java/compute/CreateInstance.java b/compute/cloud-client/src/main/java/compute/CreateInstance.java
index 15ff1196a73..6c012330f1f 100644
--- a/compute/cloud-client/src/main/java/compute/CreateInstance.java
+++ b/compute/cloud-client/src/main/java/compute/CreateInstance.java
@@ -29,11 +29,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateInstance {
public static void main(String[] args)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
String project = "your-project-id";
String zone = "zone-name";
@@ -44,15 +46,18 @@ public static void main(String[] args)
// Create a new instance with the provided "instanceName" value in the specified project and zone.
public static void createInstance(String project, String zone, String instanceName)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// Below are sample values that can be replaced.
- // machineType: machine type of the VM being created. This value uses the format zones/{zone}/machineTypes/{type_name}. For a list of machine types, see https://cloud.google.com/compute/docs/machine-types
- // sourceImage: path to the operating system image to mount. For details about images you can mount, see https://cloud.google.com/compute/docs/images
+ // machineType: machine type of the VM being created.
+ // * This value uses the format zones/{zone}/machineTypes/{type_name}.
+ // * For a list of machine types, see https://cloud.google.com/compute/docs/machine-types
+ // sourceImage: path to the operating system image to mount.
+ // * For details about images you can mount, see https://cloud.google.com/compute/docs/images
// diskSizeGb: storage size of the boot disk to attach to the instance.
// networkName: network interface to associate with the instance.
String machineType = String.format("zones/%s/machineTypes/n1-standard-1", zone);
String sourceImage = String
- .format("projects/debian-cloud/global/images/family/%s", "debian-10");
+ .format("projects/debian-cloud/global/images/family/%s", "debian-11");
long diskSizeGb = 10L;
String networkName = "default";
@@ -69,12 +74,15 @@ public static void createInstance(String project, String zone, String instanceNa
.setType(Type.PERSISTENT.toString())
.setDeviceName("disk-1")
.setInitializeParams(
- AttachedDiskInitializeParams.newBuilder().setSourceImage(sourceImage)
- .setDiskSizeGb(diskSizeGb).build())
+ AttachedDiskInitializeParams.newBuilder()
+ .setSourceImage(sourceImage)
+ .setDiskSizeGb(diskSizeGb)
+ .build())
.build();
// Use the network interface provided in the networkName argument.
- NetworkInterface networkInterface = NetworkInterface.newBuilder().setName(networkName)
+ NetworkInterface networkInterface = NetworkInterface.newBuilder()
+ .setName(networkName)
.build();
// Bind `instanceName`, `machineType`, `disk`, and `networkInterface` to an instance.
@@ -92,13 +100,14 @@ public static void createInstance(String project, String zone, String instanceNa
InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
.setProject(project)
.setZone(zone)
- .setInstanceResource(instanceResource).build();
+ .setInstanceResource(instanceResource)
+ .build();
OperationFuture operation = instancesClient.insertAsync(
insertInstanceRequest);
// Wait for the operation to complete.
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance creation failed ! ! " + response);
diff --git a/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplate.java b/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplate.java
index 6bb7e5a216d..3d8e2bea792 100644
--- a/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplate.java
+++ b/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplate.java
@@ -25,11 +25,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateInstanceFromTemplate {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* TODO(developer): Replace these variables before running the sample.
projectId - ID or number of the project you want to use.
zone - Name of the zone you want to check, for example: us-west3-b
@@ -51,7 +53,7 @@ public static void main(String[] args)
// Create a new instance from template in the specified project and zone.
public static void createInstanceFromTemplate(String projectId, String zone, String instanceName,
String instanceTemplateUrl)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstancesClient instancesClient = InstancesClient.create()) {
@@ -61,7 +63,8 @@ public static void createInstanceFromTemplate(String projectId, String zone, Str
.setInstanceResource(Instance.newBuilder().setName(instanceName).build())
.setSourceInstanceTemplate(instanceTemplateUrl).build();
- Operation response = instancesClient.insertAsync(insertInstanceRequest).get();
+ Operation response = instancesClient.insertAsync(insertInstanceRequest)
+ .get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance creation from template failed ! ! " + response);
diff --git a/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplateWithOverrides.java b/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplateWithOverrides.java
index 27bc0f92df4..3ff0e4530cb 100644
--- a/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplateWithOverrides.java
+++ b/compute/cloud-client/src/main/java/compute/CreateInstanceFromTemplateWithOverrides.java
@@ -28,11 +28,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateInstanceFromTemplateWithOverrides {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* TODO(developer): Replace these variables before running the sample.
* projectId - ID or number of the project you want to use.
* zone - Name of the zone you want to check, for example: us-west3-b
@@ -62,7 +64,7 @@ public static void main(String[] args)
// but overrides the disk and machine type options in the template.
public static void createInstanceFromTemplateWithOverrides(String projectId, String zone,
String instanceName, String instanceTemplateName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstancesClient instancesClient = InstancesClient.create();
InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {
@@ -100,7 +102,8 @@ public static void createInstanceFromTemplateWithOverrides(String projectId, Str
.setInstanceResource(instance)
.setSourceInstanceTemplate(instanceTemplate.getSelfLink()).build();
- Operation response = instancesClient.insertAsync(insertInstanceRequest).get();
+ Operation response = instancesClient.insertAsync(insertInstanceRequest)
+ .get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance creation from template with overrides failed ! ! " + response);
diff --git a/compute/cloud-client/src/main/java/compute/CreateInstanceTemplate.java b/compute/cloud-client/src/main/java/compute/CreateInstanceTemplate.java
index 9bc0db60222..f0394d13bc3 100644
--- a/compute/cloud-client/src/main/java/compute/CreateInstanceTemplate.java
+++ b/compute/cloud-client/src/main/java/compute/CreateInstanceTemplate.java
@@ -16,6 +16,7 @@
package compute;
+// [START compute_template_create]
import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.NetworkTier;
import com.google.cloud.compute.v1.AttachedDisk;
@@ -29,11 +30,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateInstanceTemplate {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// projectId: project ID or project number of the Cloud project you use.
// templateName: name of the new template to create.
@@ -47,7 +50,7 @@ public static void main(String[] args)
instance configuration.
*/
public static void createInstanceTemplate(String projectId, String templateName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {
String machineType = "e2-standard-4";
@@ -85,7 +88,8 @@ public static void createInstanceTemplate(String projectId, String templateName)
.setProperties(instanceProperties).build()).build();
// Create the Instance Template.
- Operation response = instanceTemplatesClient.insertAsync(insertInstanceTemplateRequest).get();
+ Operation response = instanceTemplatesClient.insertAsync(insertInstanceTemplateRequest)
+ .get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance Template creation failed ! ! " + response);
@@ -97,7 +101,7 @@ public static void createInstanceTemplate(String projectId, String templateName)
}
public static void createInstanceTemplateWithDiskType(String projectId, String templateName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create();
GlobalOperationsClient globalOperationsClient = GlobalOperationsClient.create()) {
@@ -122,7 +126,8 @@ public static void createInstanceTemplateWithDiskType(String projectId, String t
.setProject(projectId)
.setInstanceTemplateResource(instanceTemplate).build();
- Operation response = instanceTemplatesClient.insertAsync(insertInstanceTemplateRequest).get();
+ Operation response = instanceTemplatesClient.insertAsync(insertInstanceTemplateRequest)
+ .get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance Template creation failed ! ! " + response);
@@ -132,4 +137,5 @@ public static void createInstanceTemplateWithDiskType(String projectId, String t
.printf("Instance Template Operation Status %s: %s", templateName, response.getStatus());
}
}
-}
\ No newline at end of file
+}
+// [END compute_template_create]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/CreateInstancesAdvanced.java b/compute/cloud-client/src/main/java/compute/CreateInstancesAdvanced.java
index 1c6c2217ded..dad7c6f6372 100644
--- a/compute/cloud-client/src/main/java/compute/CreateInstancesAdvanced.java
+++ b/compute/cloud-client/src/main/java/compute/CreateInstancesAdvanced.java
@@ -37,6 +37,8 @@
import java.io.IOException;
import java.util.Vector;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateInstancesAdvanced {
// [END compute_instances_create_from_image]
@@ -195,7 +197,7 @@ private static AttachedDisk diskFromSnapshot(String diskType, int diskSizeGb, bo
*/
private static Instance createWithDisks(String project, String zone, String instanceName,
Vector disks, String machineType, String network, String subnetwork)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
try (InstancesClient instancesClient = InstancesClient.create()) {
// Use the network interface provided in the networkName argument.
NetworkInterface networkInterface;
@@ -231,7 +233,7 @@ private static Instance createWithDisks(String project, String zone, String inst
insertInstanceRequest);
// Wait for the operation to complete.
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance creation failed ! ! " + response);
@@ -260,7 +262,7 @@ private static Instance createWithDisks(String project, String zone, String inst
* @return Instance object.
*/
public static Instance createFromPublicImage(String project, String zone, String instanceName)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
try (ImagesClient imagesClient = ImagesClient.create()) {
// List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
Image image = imagesClient.getFromFamily("debian-cloud", "debian-10");
@@ -287,7 +289,7 @@ public static Instance createFromPublicImage(String project, String zone, String
*/
public static Instance createFromCustomImage(String project, String zone, String instanceName,
String customImage)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
String diskType = String.format("zones/%s/diskTypes/pd-standard", zone);
Vector disks = new Vector<>();
disks.add(diskFromImage(diskType, 10, true, customImage));
@@ -307,7 +309,7 @@ public static Instance createFromCustomImage(String project, String zone, String
* @return Instance object.
*/
public static Instance createWithAdditionalDisk(String project, String zone, String instanceName)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
try (ImagesClient imagesClient = ImagesClient.create()) {
// List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
Image image = imagesClient.getFromFamily("debian-cloud", "debian-10");
@@ -335,7 +337,7 @@ public static Instance createWithAdditionalDisk(String project, String zone, Str
*/
public static Instance createFromSnapshot(String project, String zone, String instanceName,
String snapshotName)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
String diskType = String.format("zones/%s/diskTypes/pd-standard", zone);
Vector disks = new Vector<>();
disks.add(diskFromSnapshot(diskType, 11, true, snapshotName));
@@ -358,7 +360,7 @@ public static Instance createFromSnapshot(String project, String zone, String in
*/
public static Instance createWithSnapshottedDataDisk(String project, String zone,
String instanceName, String snapshotName)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
try (ImagesClient imagesClient = ImagesClient.create()) {
// List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
Image image = imagesClient.getFromFamily("debian-cloud", "debian-10");
@@ -389,7 +391,7 @@ public static Instance createWithSnapshottedDataDisk(String project, String zone
*/
public static Instance createWithSubnetwork(String project, String zone, String instanceName,
String networkLink, String subnetworkLink)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
try (ImagesClient imagesClient = ImagesClient.create()) {
// List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
Image image = imagesClient.getFromFamily("debian-cloud", "debian-10");
diff --git a/compute/cloud-client/src/main/java/compute/CreateTemplateFromInstance.java b/compute/cloud-client/src/main/java/compute/CreateTemplateFromInstance.java
index 1e766647931..1d9595972d4 100644
--- a/compute/cloud-client/src/main/java/compute/CreateTemplateFromInstance.java
+++ b/compute/cloud-client/src/main/java/compute/CreateTemplateFromInstance.java
@@ -28,11 +28,13 @@
import com.google.cloud.compute.v1.SourceInstanceParams;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateTemplateFromInstance {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// projectId: project ID or project number of the Cloud project you use.
// instance: the instance to base the new template on. This value uses the following format:
@@ -49,7 +51,7 @@ public static void main(String[] args)
// This new template specifies a different boot disk.
public static void createTemplateFromInstance(String projectId, String templateName,
String instance)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create();
GlobalOperationsClient globalOperationsClient = GlobalOperationsClient.create()) {
@@ -81,7 +83,7 @@ public static void createTemplateFromInstance(String projectId, String templateN
.build();
Operation operation = instanceTemplatesClient.insertCallable()
- .futureCall(insertInstanceTemplateRequest).get();
+ .futureCall(insertInstanceTemplateRequest).get(3, TimeUnit.MINUTES);
Operation response = globalOperationsClient.wait(projectId, operation.getName());
diff --git a/compute/cloud-client/src/main/java/compute/CreateTemplateWithSubnet.java b/compute/cloud-client/src/main/java/compute/CreateTemplateWithSubnet.java
index f92ae6f65cd..602db9d2d57 100644
--- a/compute/cloud-client/src/main/java/compute/CreateTemplateWithSubnet.java
+++ b/compute/cloud-client/src/main/java/compute/CreateTemplateWithSubnet.java
@@ -29,11 +29,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateTemplateWithSubnet {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/*
TODO(developer): Replace these variables before running the sample.
projectId: project ID or project number of the Cloud project you use.
@@ -54,7 +56,7 @@ public static void main(String[] args)
// Create an instance template that uses a provided subnet.
public static void createTemplateWithSubnet(String projectId, String network, String subnetwork,
String templateName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create();
GlobalOperationsClient globalOperationsClient = GlobalOperationsClient.create()) {
@@ -87,7 +89,7 @@ public static void createTemplateWithSubnet(String projectId, String network, St
.build();
Operation operation = instanceTemplatesClient.insertCallable()
- .futureCall(insertInstanceTemplateRequest).get();
+ .futureCall(insertInstanceTemplateRequest).get(3, TimeUnit.MINUTES);
Operation response = globalOperationsClient.wait(projectId, operation.getName());
diff --git a/compute/cloud-client/src/main/java/compute/DeleteFirewallRule.java b/compute/cloud-client/src/main/java/compute/DeleteFirewallRule.java
index aa755db0883..0985adc6c3a 100644
--- a/compute/cloud-client/src/main/java/compute/DeleteFirewallRule.java
+++ b/compute/cloud-client/src/main/java/compute/DeleteFirewallRule.java
@@ -24,11 +24,13 @@
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class DeleteFirewallRule {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample
// project: project ID or project number of the Cloud project you want to use.
// firewallRuleName: name of the firewall rule you want to delete.
@@ -40,7 +42,7 @@ public static void main(String[] args)
// Deletes a firewall rule from the project.
public static void deleteFirewallRule(String project, String firewallRuleName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* Initialize client that will be used to send requests. This client only needs to be created
once, and can be reused for multiple requests. After completing all of your requests, call
the `firewallsClient.close()` method on the client to safely
@@ -49,7 +51,7 @@ public static void deleteFirewallRule(String project, String firewallRuleName)
OperationFuture operation = firewallsClient.deleteAsync(project,
firewallRuleName);
- operation.get();
+ operation.get(3, TimeUnit.MINUTES);
System.out.println("Deleted firewall rule -> " + firewallRuleName);
}
diff --git a/compute/cloud-client/src/main/java/compute/DeleteInstance.java b/compute/cloud-client/src/main/java/compute/DeleteInstance.java
index f5279aa485b..f3533778ec7 100644
--- a/compute/cloud-client/src/main/java/compute/DeleteInstance.java
+++ b/compute/cloud-client/src/main/java/compute/DeleteInstance.java
@@ -24,11 +24,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class DeleteInstance {
public static void main(String[] args)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
String project = "your-project-id";
String zone = "zone-name";
@@ -39,7 +41,7 @@ public static void main(String[] args)
// Delete the instance specified by `instanceName`
// if it's present in the given project and zone.
public static void deleteInstance(String project, String zone, String instanceName)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the `instancesClient.close()` method on the client to safely
@@ -57,7 +59,7 @@ public static void deleteInstance(String project, String zone, String instanceNa
OperationFuture operation = instancesClient.deleteAsync(
deleteInstanceRequest);
// Wait for the operation to complete.
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance deletion failed ! ! " + response);
diff --git a/compute/cloud-client/src/main/java/compute/DeleteInstanceTemplate.java b/compute/cloud-client/src/main/java/compute/DeleteInstanceTemplate.java
index 604c4f6d1f6..3c3fa07c024 100644
--- a/compute/cloud-client/src/main/java/compute/DeleteInstanceTemplate.java
+++ b/compute/cloud-client/src/main/java/compute/DeleteInstanceTemplate.java
@@ -16,16 +16,20 @@
package compute;
+// [START compute_template_delete]
+
import com.google.cloud.compute.v1.DeleteInstanceTemplateRequest;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class DeleteInstanceTemplate {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// projectId: project ID or project number of the Cloud project you use.
// templateName: name of the new template to create.
@@ -36,7 +40,7 @@ public static void main(String[] args)
// Delete an instance template.
public static void deleteInstanceTemplate(String projectId, String templateName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {
DeleteInstanceTemplateRequest deleteInstanceTemplateRequest = DeleteInstanceTemplateRequest
@@ -44,7 +48,8 @@ public static void deleteInstanceTemplate(String projectId, String templateName)
.setProject(projectId)
.setInstanceTemplate(templateName).build();
- Operation response = instanceTemplatesClient.deleteAsync(deleteInstanceTemplateRequest).get();
+ Operation response = instanceTemplatesClient.deleteAsync(deleteInstanceTemplateRequest)
+ .get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance template deletion failed ! ! " + response);
@@ -54,4 +59,5 @@ public static void deleteInstanceTemplate(String projectId, String templateName)
response.getStatus());
}
}
-}
\ No newline at end of file
+}
+// [END compute_template_delete]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/GetInstanceTemplate.java b/compute/cloud-client/src/main/java/compute/GetInstanceTemplate.java
index d08f2752b38..f82476cfc2e 100644
--- a/compute/cloud-client/src/main/java/compute/GetInstanceTemplate.java
+++ b/compute/cloud-client/src/main/java/compute/GetInstanceTemplate.java
@@ -16,6 +16,8 @@
package compute;
+// [START compute_template_get]
+
import com.google.cloud.compute.v1.GetInstanceTemplateRequest;
import com.google.cloud.compute.v1.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
@@ -26,7 +28,7 @@ public class GetInstanceTemplate {
public static void main(String[] args) throws IOException {
// TODO(developer): Replace these variables before running the sample.
// projectId: project ID or project number of the Cloud project you use.
- // templateName: name of the new template to retrieve.
+ // templateName: name of the template to retrieve.
String projectId = "your-project-id";
String templateName = "template-name";
getInstanceTemplate(projectId, templateName);
@@ -46,4 +48,5 @@ public static void getInstanceTemplate(String projectId, String templateName) th
System.out.println("Instance Template retrieved: " + instanceTemplate.getName());
}
}
-}
\ No newline at end of file
+}
+// [END compute_template_get]
diff --git a/compute/cloud-client/src/main/java/compute/ListInstanceTemplates.java b/compute/cloud-client/src/main/java/compute/ListInstanceTemplates.java
index c029d8acd4a..917311ac98e 100644
--- a/compute/cloud-client/src/main/java/compute/ListInstanceTemplates.java
+++ b/compute/cloud-client/src/main/java/compute/ListInstanceTemplates.java
@@ -16,6 +16,8 @@
package compute;
+// [START compute_template_list]
+
import com.google.cloud.compute.v1.InstanceTemplate;
import com.google.cloud.compute.v1.InstanceTemplatesClient;
import com.google.cloud.compute.v1.InstanceTemplatesClient.ListPagedResponse;
@@ -42,4 +44,5 @@ public static ListPagedResponse listInstanceTemplates(String projectId) throws I
return templates;
}
}
-}
\ No newline at end of file
+}
+// [END compute_template_list]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/PatchFirewallRule.java b/compute/cloud-client/src/main/java/compute/PatchFirewallRule.java
index d7e7f91f87a..5cbda7d58e4 100644
--- a/compute/cloud-client/src/main/java/compute/PatchFirewallRule.java
+++ b/compute/cloud-client/src/main/java/compute/PatchFirewallRule.java
@@ -26,11 +26,13 @@
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class PatchFirewallRule {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample
// project: project ID or project number of the Cloud project you want to use.
// firewallRuleName: name of the rule you want to modify.
@@ -44,7 +46,7 @@ public static void main(String[] args)
// Modifies the priority of a given firewall rule.
public static void patchFirewallPriority(String project, String firewallRuleName, int priority)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* Initialize client that will be used to send requests. This client only needs to be created
once, and can be reused for multiple requests. After completing all of your requests, call
the `firewallsClient.close()` method on the client to safely
@@ -63,7 +65,7 @@ public static void patchFirewallPriority(String project, String firewallRuleName
OperationFuture operation = firewallsClient.patchAsync(
patchFirewallRequest);
- operation.get();
+ operation.get(3, TimeUnit.MINUTES);
System.out.println("Firewall Patch applied successfully ! ");
}
}
diff --git a/compute/cloud-client/src/main/java/compute/ResetInstance.java b/compute/cloud-client/src/main/java/compute/ResetInstance.java
index 480f412f699..ed6381e5759 100644
--- a/compute/cloud-client/src/main/java/compute/ResetInstance.java
+++ b/compute/cloud-client/src/main/java/compute/ResetInstance.java
@@ -25,11 +25,13 @@
import com.google.cloud.compute.v1.ResetInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class ResetInstance {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
/* project: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
@@ -44,7 +46,7 @@ public static void main(String[] args)
// Resets a running Google Compute Engine instance (with unencrypted disks).
public static void resetInstance(String project, String zone, String instanceName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* Initialize client that will be used to send requests. This client only needs to be created
once, and can be reused for multiple requests. After completing all of your requests, call
the `instancesClient.close()` method on the client to safely
@@ -59,7 +61,7 @@ public static void resetInstance(String project, String zone, String instanceNam
OperationFuture operation = instancesClient.resetAsync(
resetInstanceRequest);
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.getStatus() == Status.DONE) {
System.out.println("Instance reset successfully ! ");
diff --git a/compute/cloud-client/src/main/java/compute/ResumeInstance.java b/compute/cloud-client/src/main/java/compute/ResumeInstance.java
new file mode 100644
index 00000000000..314e7e0c12f
--- /dev/null
+++ b/compute/cloud-client/src/main/java/compute/ResumeInstance.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package compute;
+
+// [START compute_resume_instance]
+
+import com.google.cloud.compute.v1.Instance.Status;
+import com.google.cloud.compute.v1.InstancesClient;
+import com.google.cloud.compute.v1.Operation;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class ResumeInstance {
+
+ public static void main(String[] args)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // TODO(developer): Replace these variables before running the sample.
+ // project: project ID or project number of the Cloud project your instance belongs to.
+ // zone: name of the zone your instance belongs to.
+ // instanceName: name of the instance your want to resume.
+
+ String project = "your-project-id";
+ String zone = "zone-name";
+ String instanceName = "instance-name";
+
+ resumeInstance(project, zone, instanceName);
+ }
+
+ // Resume a suspended Google Compute Engine instance (with unencrypted disks).
+ // Instance state changes to RUNNING, if successfully resumed.
+ public static void resumeInstance(String project, String zone, String instanceName)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // Instantiates a client.
+ try (InstancesClient instancesClient = InstancesClient.create()) {
+
+ String currentInstanceState = instancesClient.get(project, zone, instanceName).getStatus();
+
+ // Check if the instance is currently suspended.
+ if (!currentInstanceState.equalsIgnoreCase(Status.SUSPENDED.toString())) {
+ throw new RuntimeException(
+ String.format("Only suspended instances can be resumed. Instance %s is in %s state.",
+ instanceName, currentInstanceState));
+ }
+
+ Operation operation = instancesClient.resumeAsync(project, zone, instanceName)
+ .get(300, TimeUnit.SECONDS);
+
+ if (operation.hasError() || !instancesClient.get(project, zone, instanceName).getStatus()
+ .equalsIgnoreCase(
+ Status.RUNNING.toString())) {
+ System.out.println("Cannot resume instance. Try again!");
+ return;
+ }
+
+ System.out.printf("Instance resumed successfully ! %s", instanceName);
+ }
+ }
+}
+// [END compute_resume_instance]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/SetUsageExportBucket.java b/compute/cloud-client/src/main/java/compute/SetUsageExportBucket.java
index faf7a3bf9b7..4ffc676aac2 100644
--- a/compute/cloud-client/src/main/java/compute/SetUsageExportBucket.java
+++ b/compute/cloud-client/src/main/java/compute/SetUsageExportBucket.java
@@ -32,6 +32,7 @@
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
// [END compute_usage_report_disable]
// [END compute_usage_report_get]
@@ -40,7 +41,7 @@
public class SetUsageExportBucket {
public static void main(String[] args)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// TODO(developer): Create a Google Cloud Storage bucket.
// bucketName: Cloud Storage Bucket used to store Compute Engine usage reports.
@@ -59,7 +60,7 @@ public static void main(String[] args)
// This sample presents how to interpret the default value for the report name prefix parameter.
public static void setUsageExportBucket(String project, String bucketName,
String reportNamePrefix)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// bucketName: Cloud Storage Bucket used to store Compute Engine usage reports.
// An existing Google Cloud Storage bucket is required.
@@ -89,7 +90,7 @@ public static void setUsageExportBucket(String project, String bucketName,
.build());
// Wait for the operation to complete.
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Setting usage export bucket failed ! ! " + response);
@@ -143,7 +144,7 @@ public static UsageExportLocation getUsageExportBucket(String project) throws IO
// Disable Compute Engine usage export bucket for the Cloud project.
public static boolean disableUsageExportBucket(String project)
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
try (ProjectsClient projectsClient = ProjectsClient.create()) {
@@ -158,7 +159,8 @@ public static boolean disableUsageExportBucket(String project)
.build());
// Wait for the operation to complete.
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
+ ;
if (response.hasError()) {
System.out.println("Disable usage export bucket failed ! ! " + response);
@@ -166,7 +168,7 @@ public static boolean disableUsageExportBucket(String project)
}
// Wait for the settings to be effected.
- TimeUnit.SECONDS.sleep(5);
+ TimeUnit.SECONDS.sleep(15);
// Return false if the usage reports is disabled.
return projectsClient.get(project).getUsageExportLocation().hasBucketName();
}
diff --git a/compute/cloud-client/src/main/java/compute/StartEncryptedInstance.java b/compute/cloud-client/src/main/java/compute/StartEncryptedInstance.java
index 7dc0eb70102..9e5b2b62704 100644
--- a/compute/cloud-client/src/main/java/compute/StartEncryptedInstance.java
+++ b/compute/cloud-client/src/main/java/compute/StartEncryptedInstance.java
@@ -30,11 +30,13 @@
import com.google.cloud.compute.v1.StartWithEncryptionKeyInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class StartEncryptedInstance {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
/* project: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
@@ -54,7 +56,7 @@ public static void main(String[] args)
// Starts a stopped Google Compute Engine instance (with encrypted disks).
public static void startEncryptedInstance(String project, String zone, String instanceName,
String key)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* Initialize client that will be used to send requests. This client only needs to be created
once, and can be reused for multiple requests. After completing all of your requests, call
the `instancesClient.close()` method on the client to safely
@@ -94,7 +96,7 @@ public static void startEncryptedInstance(String project, String zone, String in
OperationFuture operation = instancesClient.startWithEncryptionKeyAsync(
encryptionKeyInstanceRequest);
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.getStatus() == Status.DONE) {
System.out.println("Encrypted instance started successfully ! ");
diff --git a/compute/cloud-client/src/main/java/compute/StartInstance.java b/compute/cloud-client/src/main/java/compute/StartInstance.java
index 4bcf20de89e..3c8ab90bb7e 100644
--- a/compute/cloud-client/src/main/java/compute/StartInstance.java
+++ b/compute/cloud-client/src/main/java/compute/StartInstance.java
@@ -25,11 +25,13 @@
import com.google.cloud.compute.v1.StartInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class StartInstance {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
/* project: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
@@ -43,7 +45,7 @@ public static void main(String[] args)
// Starts a stopped Google Compute Engine instance (with unencrypted disks).
public static void startInstance(String project, String zone, String instanceName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* Initialize client that will be used to send requests. This client only needs to be created
once, and can be reused for multiple requests. After completing all of your requests, call
the `instancesClient.close()` method on the client to safely
@@ -61,7 +63,7 @@ public static void startInstance(String project, String zone, String instanceNam
startInstanceRequest);
// Wait for the operation to complete.
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.getStatus() == Status.DONE) {
System.out.println("Instance started successfully ! ");
diff --git a/compute/cloud-client/src/main/java/compute/StopInstance.java b/compute/cloud-client/src/main/java/compute/StopInstance.java
index 7fd341b5ee5..ce22aa11458 100644
--- a/compute/cloud-client/src/main/java/compute/StopInstance.java
+++ b/compute/cloud-client/src/main/java/compute/StopInstance.java
@@ -25,11 +25,13 @@
import com.google.cloud.compute.v1.StopInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class StopInstance {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
/* project: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
@@ -44,7 +46,7 @@ public static void main(String[] args)
// Stops a started Google Compute Engine instance.
public static void stopInstance(String project, String zone, String instanceName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
/* Initialize client that will be used to send requests. This client only needs to be created
once, and can be reused for multiple requests. After completing all of your requests, call
the `instancesClient.close()` method on the client to safely
@@ -59,7 +61,7 @@ public static void stopInstance(String project, String zone, String instanceName
OperationFuture operation = instancesClient.stopAsync(
stopInstanceRequest);
- Operation response = operation.get();
+ Operation response = operation.get(3, TimeUnit.MINUTES);
if (response.getStatus() == Status.DONE) {
System.out.println("Instance stopped successfully ! ");
diff --git a/compute/cloud-client/src/main/java/compute/SuspendInstance.java b/compute/cloud-client/src/main/java/compute/SuspendInstance.java
new file mode 100644
index 00000000000..458b83680bd
--- /dev/null
+++ b/compute/cloud-client/src/main/java/compute/SuspendInstance.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package compute;
+
+// [START compute_suspend_instance]
+
+import com.google.cloud.compute.v1.Instance.Status;
+import com.google.cloud.compute.v1.InstancesClient;
+import com.google.cloud.compute.v1.Operation;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class SuspendInstance {
+
+ public static void main(String[] args)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // TODO(developer): Replace these variables before running the sample.
+ // project: project ID or project number of the Cloud project your instance belongs to.
+ // zone: name of the zone your instance belongs to.
+ // instanceName: name of the instance your want to suspend.
+
+ String project = "your-project-id";
+ String zone = "zone-name";
+ String instanceName = "instance-name";
+
+ suspendInstance(project, zone, instanceName);
+ }
+
+ // Suspend a running Google Compute Engine instance.
+ // For limitations and compatibility on which instances can be suspended,
+ // see: https://cloud.google.com/compute/docs/instances/suspend-resume-instance#limitations
+ public static void suspendInstance(String project, String zone, String instanceName)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // Instantiates a client.
+ try (InstancesClient instancesClient = InstancesClient.create()) {
+
+ Operation operation = instancesClient.suspendAsync(project, zone, instanceName)
+ .get(300, TimeUnit.SECONDS);
+
+ if (operation.hasError() || !instancesClient.get(project, zone, instanceName).getStatus()
+ .equalsIgnoreCase(Status.SUSPENDED.toString())) {
+ System.out.println("Cannot suspend instance. Try again!");
+ return;
+ }
+
+ System.out.printf("Instance suspended successfully ! %s", instanceName);
+ }
+ }
+}
+// [END compute_suspend_instance]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/customhostname/CreateInstanceWithCustomHostname.java b/compute/cloud-client/src/main/java/compute/customhostname/CreateInstanceWithCustomHostname.java
index 03238336edc..03f07491a37 100644
--- a/compute/cloud-client/src/main/java/compute/customhostname/CreateInstanceWithCustomHostname.java
+++ b/compute/cloud-client/src/main/java/compute/customhostname/CreateInstanceWithCustomHostname.java
@@ -27,11 +27,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateInstanceWithCustomHostname {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// hostName: Custom hostname of the new VM instance.
// * Custom hostnames must conform to RFC 1035 requirements for valid hostnames.
@@ -45,7 +47,7 @@ public static void main(String[] args)
// Creates an instance with custom hostname.
public static void createInstanceWithCustomHostname(String projectId, String zone,
String instanceName, String hostName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// machineType - Machine type for the VM instance specified in the following format:
// * "zones/{zone}/machineTypes/{type_name}". For example:
// * "zones/europe-west3-c/machineTypes/f1-micro"
@@ -101,7 +103,8 @@ public static void createInstanceWithCustomHostname(String projectId, String zon
.setInstanceResource(instanceResource).build();
// Wait for the create operation to complete.
- Operation response = instancesClient.insertAsync(request).get();
+ Operation response = instancesClient.insertAsync(request).get(3, TimeUnit.MINUTES);
+ ;
if (response.hasError()) {
System.out.printf("Instance creation failed for instance: %s ; Response: %s ! ! ",
diff --git a/compute/cloud-client/src/main/java/compute/deleteprotection/CreateInstanceDeleteProtection.java b/compute/cloud-client/src/main/java/compute/deleteprotection/CreateInstanceDeleteProtection.java
index c8fafb7e5f1..71b880e2301 100644
--- a/compute/cloud-client/src/main/java/compute/deleteprotection/CreateInstanceDeleteProtection.java
+++ b/compute/cloud-client/src/main/java/compute/deleteprotection/CreateInstanceDeleteProtection.java
@@ -27,11 +27,13 @@
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreateInstanceDeleteProtection {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// project: project ID or project number of the Cloud project you want to use.
// zone: name of the zone you want to use. For example: “us-west3-b”
@@ -48,7 +50,7 @@ public static void main(String[] args)
// Send an instance creation request to the Compute Engine API and wait for it to complete.
public static void createInstanceDeleteProtection(String projectId, String zone,
String instanceName, boolean deleteProtection)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
String machineType = String.format("zones/%s/machineTypes/e2-small", zone);
String sourceImage = String
@@ -98,7 +100,9 @@ public static void createInstanceDeleteProtection(String projectId, String zone,
.build();
// Wait for the create operation to complete.
- Operation response = instancesClient.insertAsync(insertInstanceRequest).get();
+ Operation response = instancesClient.insertAsync(insertInstanceRequest)
+ .get(3, TimeUnit.MINUTES);
+ ;
if (response.hasError()) {
System.out.println("Instance creation failed ! ! " + response);
diff --git a/compute/cloud-client/src/main/java/compute/deleteprotection/SetDeleteProtection.java b/compute/cloud-client/src/main/java/compute/deleteprotection/SetDeleteProtection.java
index 13df47926a0..3720261d3a4 100644
--- a/compute/cloud-client/src/main/java/compute/deleteprotection/SetDeleteProtection.java
+++ b/compute/cloud-client/src/main/java/compute/deleteprotection/SetDeleteProtection.java
@@ -22,11 +22,13 @@
import com.google.cloud.compute.v1.SetDeletionProtectionInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class SetDeleteProtection {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// project: project ID or project number of the Cloud project you want to use.
// zone: name of the zone you want to use. For example: “us-west3-b”
@@ -43,7 +45,7 @@ public static void main(String[] args)
// Updates the "Delete Protection" setting of given instance.
public static void setDeleteProtection(String projectId, String zone,
String instanceName, boolean deleteProtection)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
try (InstancesClient instancesClient = InstancesClient.create()) {
@@ -55,7 +57,8 @@ public static void setDeleteProtection(String projectId, String zone,
.setDeletionProtection(deleteProtection)
.build();
- instancesClient.setDeletionProtectionAsync(request).get();
+ instancesClient.setDeletionProtectionAsync(request).get(3, TimeUnit.MINUTES);
+ ;
// Retrieve the updated setting from the instance.
System.out.printf("Updated Delete Protection setting: %s",
instancesClient.get(projectId, zone, instanceName).getDeletionProtection());
diff --git a/compute/cloud-client/src/main/java/compute/preemptible/CreatePreemptibleInstance.java b/compute/cloud-client/src/main/java/compute/preemptible/CreatePreemptibleInstance.java
index 05c2ce0c6c0..2965512eb4a 100644
--- a/compute/cloud-client/src/main/java/compute/preemptible/CreatePreemptibleInstance.java
+++ b/compute/cloud-client/src/main/java/compute/preemptible/CreatePreemptibleInstance.java
@@ -28,11 +28,13 @@
import com.google.cloud.compute.v1.Scheduling;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CreatePreemptibleInstance {
public static void main(String[] args)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// projectId: project ID or project number of the Cloud project you want to use.
// zone: name of the zone you want to use. For example: “us-west3-b”
@@ -47,7 +49,7 @@ public static void main(String[] args)
// Send an instance creation request with preemptible settings to the Compute Engine API
// and wait for it to complete.
public static void createPremptibleInstance(String projectId, String zone, String instanceName)
- throws IOException, ExecutionException, InterruptedException {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
String machineType = String.format("zones/%s/machineTypes/e2-small", zone);
String sourceImage = "projects/debian-cloud/global/images/family/debian-11";
@@ -97,7 +99,9 @@ public static void createPremptibleInstance(String projectId, String zone, Strin
.build();
// Wait for the create operation to complete.
- Operation response = instancesClient.insertAsync(insertInstanceRequest).get();
+ Operation response = instancesClient.insertAsync(insertInstanceRequest)
+ .get(3, TimeUnit.MINUTES);
+ ;
if (response.hasError()) {
System.out.println("Instance creation failed ! ! " + response);
diff --git a/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateFirewallRuleForWindowsActivationHost.java b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateFirewallRuleForWindowsActivationHost.java
new file mode 100644
index 00000000000..b741c47fa0b
--- /dev/null
+++ b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateFirewallRuleForWindowsActivationHost.java
@@ -0,0 +1,88 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compute.windows.windowsinstances;
+
+// [START compute_create_egress_rule_windows_activation]
+
+import com.google.cloud.compute.v1.Allowed;
+import com.google.cloud.compute.v1.Firewall;
+import com.google.cloud.compute.v1.FirewallsClient;
+import com.google.cloud.compute.v1.InsertFirewallRequest;
+import com.google.cloud.compute.v1.Operation;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class CreateFirewallRuleForWindowsActivationHost {
+
+ public static void main(String[] args)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // TODO(developer): Replace these variables before running the sample.
+ // projectId - ID or number of the project you want to use.
+ String projectId = "your-google-cloud-project-id";
+
+ // firewallRuleName - Name of the firewall rule you want to create.
+ String firewallRuleName = "firewall-rule-name";
+
+ // networkName - Name of the network you want the new instance to use.
+ // * For example: "global/networks/default" represents the network
+ // * named "default", which is created automatically for each project.
+ String networkName = "global/networks/default";
+
+ createFirewallRuleForWindowsActivationHost(projectId, firewallRuleName, networkName);
+ }
+
+ // Creates a new allow egress firewall rule with the highest priority for host
+ // kms.windows.googlecloud.com (35.190.247.13) for Windows activation.
+ public static void createFirewallRuleForWindowsActivationHost(String projectId,
+ String firewallRuleName, String networkName)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // Instantiates a client.
+ try (FirewallsClient firewallsClient = FirewallsClient.create()) {
+
+ Firewall firewall = Firewall.newBuilder()
+ .setName(firewallRuleName)
+ // These are the default values for kms.windows.googlecloud.com
+ // See, https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#firewall_rule_requirements
+ .addAllowed(Allowed.newBuilder()
+ .setIPProtocol("tcp")
+ .addPorts("1688")
+ .build())
+ .setDirection("EGRESS")
+ .setNetwork(networkName)
+ .addDestinationRanges("35.190.247.13/32")
+ .setPriority(0)
+ .build();
+
+ InsertFirewallRequest request = InsertFirewallRequest.newBuilder()
+ .setProject(projectId)
+ .setFirewallResource(firewall)
+ .build();
+
+ // Wait for the operation to complete.
+ Operation operation = firewallsClient.insertAsync(request).get(3, TimeUnit.MINUTES);
+ ;
+
+ if (operation.hasError()) {
+ System.out.println("Firewall rule creation failed ! ! " + operation.getError());
+ return;
+ }
+
+ System.out.printf("Firewall rule created %s", firewallRuleName);
+ }
+ }
+}
+// [END compute_create_egress_rule_windows_activation]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateRouteToWindowsActivationHost.java b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateRouteToWindowsActivationHost.java
new file mode 100644
index 00000000000..8c9cd06a57b
--- /dev/null
+++ b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateRouteToWindowsActivationHost.java
@@ -0,0 +1,85 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compute.windows.windowsinstances;
+
+// [START compute_create_route_windows_activation]
+
+import com.google.cloud.compute.v1.InsertRouteRequest;
+import com.google.cloud.compute.v1.Operation;
+import com.google.cloud.compute.v1.Route;
+import com.google.cloud.compute.v1.RoutesClient;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class CreateRouteToWindowsActivationHost {
+
+ public static void main(String[] args)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // TODO(developer): Replace these variables before running the sample.
+ // projectId - ID or number of the project you want to use.
+ String projectId = "your-google-cloud-project-id";
+
+ // routeName - Name of the route you want to create.
+ String routeName = "route-name";
+
+ // networkName - Name of the network you want the new instance to use.
+ // * For example: "global/networks/default" represents the network
+ // * named "default", which is created automatically for each project.
+ String networkName = "global/networks/default";
+
+ createRouteToWindowsActivationHost(projectId, routeName, networkName);
+ }
+
+ // Creates a new route to kms.windows.googlecloud.com (35.190.247.13) for Windows activation.
+ public static void createRouteToWindowsActivationHost(String projectId, String routeName,
+ String networkName)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // Instantiates a client.
+ try (RoutesClient routesClient = RoutesClient.create()) {
+
+ // If you have Windows instances without external IP addresses,
+ // you must also enable Private Google Access so that instances
+ // with only internal IP addresses can send traffic to the external
+ // IP address for kms.windows.googlecloud.com.
+ // More information: https://cloud.google.com/vpc/docs/configure-private-google-access#enabling
+ Route route = Route.newBuilder()
+ .setName(routeName)
+ .setDestRange("35.190.247.13/32")
+ .setNetwork(networkName)
+ .setNextHopGateway(
+ String.format("projects/%s/global/gateways/default-internet-gateway", projectId))
+ .build();
+
+ InsertRouteRequest request = InsertRouteRequest.newBuilder()
+ .setProject(projectId)
+ .setRouteResource(route)
+ .build();
+
+ // Wait for the operation to complete.
+ Operation operation = routesClient.insertAsync(request).get(3, TimeUnit.MINUTES);
+ ;
+
+ if (operation.hasError()) {
+ System.out.printf("Error in creating route %s", operation.getError());
+ return;
+ }
+
+ System.out.printf("Route created %s", routeName);
+ }
+ }
+}
+// [END compute_create_route_windows_activation]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateWindowsServerInstanceExternalIp.java b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateWindowsServerInstanceExternalIp.java
new file mode 100644
index 00000000000..84367a26b57
--- /dev/null
+++ b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateWindowsServerInstanceExternalIp.java
@@ -0,0 +1,122 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compute.windows.windowsinstances;
+
+// [START compute_create_windows_instance_external_ip]
+
+import com.google.cloud.compute.v1.AccessConfig;
+import com.google.cloud.compute.v1.AttachedDisk;
+import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
+import com.google.cloud.compute.v1.InsertInstanceRequest;
+import com.google.cloud.compute.v1.Instance;
+import com.google.cloud.compute.v1.InstancesClient;
+import com.google.cloud.compute.v1.NetworkInterface;
+import com.google.cloud.compute.v1.Operation;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class CreateWindowsServerInstanceExternalIp {
+
+ public static void main(String[] args)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // TODO(developer): Replace these variables before running the sample.
+ // projectId - ID or number of the project you want to use.
+ String projectId = "your-google-cloud-project-id";
+
+ // zone - Name of the zone you want to use, for example: us-west3-b
+ String zone = "europe-central2-b";
+
+ // instanceName - Name of the new machine.
+ String instanceName = "instance-name";
+
+ createWindowsServerInstanceExternalIp(projectId, zone, instanceName);
+ }
+
+ // Creates a new Windows Server instance that has an external IP address.
+ public static void createWindowsServerInstanceExternalIp(String projectId, String zone,
+ String instanceName)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+
+ // machineType - Machine type you want to create in following format:
+ // * "zones/{zone}/machineTypes/{type_name}". For example:
+ // * "zones/europe-west3-c/machineTypes/f1-micro"
+ // * You can find the list of available machine types using:
+ // * https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
+ String machineType = "n1-standard-1";
+ // sourceImageFamily - Name of the public image family for Windows Server or SQL Server images.
+ // * https://cloud.google.com/compute/docs/images#os-compute-support
+ String sourceImageFamily = "windows-2012-r2";
+
+ // Instantiates a client.
+ try (InstancesClient instancesClient = InstancesClient.create()) {
+
+ AttachedDisk attachedDisk = AttachedDisk.newBuilder()
+ // Describe the size and source image of the boot disk to attach to the instance.
+ .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
+ .setDiskSizeGb(64)
+ .setSourceImage(
+ String.format("projects/windows-cloud/global/images/family/%s",
+ sourceImageFamily))
+ .build())
+ .setAutoDelete(true)
+ .setBoot(true)
+ .setType(AttachedDisk.Type.PERSISTENT.toString())
+ .build();
+
+ Instance instance = Instance.newBuilder()
+ .setName(instanceName)
+ .setMachineType(String.format("zones/%s/machineTypes/%s", zone, machineType))
+ .addDisks(attachedDisk)
+ .addNetworkInterfaces(NetworkInterface.newBuilder()
+ .addAccessConfigs(AccessConfig.newBuilder()
+ .setType("ONE_TO_ONE_NAT")
+ .setName("External NAT")
+ .build())
+ // If you going you use custom VPC network, it must be configured
+ // to allow access to kms.windows.googlecloud.com.
+ // https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server.
+ .setName("global/networks/default")
+ .build())
+ // If you chose an image that supports Shielded VM, you can optionally change the
+ // instance's Shielded VM settings.
+ // .setShieldedInstanceConfig(ShieldedInstanceConfig.newBuilder()
+ // .setEnableSecureBoot(true)
+ // .setEnableVtpm(true)
+ // .setEnableIntegrityMonitoring(true)
+ // .build())
+ .build();
+
+ InsertInstanceRequest request = InsertInstanceRequest.newBuilder()
+ .setProject(projectId)
+ .setZone(zone)
+ .setInstanceResource(instance)
+ .build();
+
+ // Wait for the operation to complete.
+ Operation operation = instancesClient.insertAsync(request).get(3, TimeUnit.MINUTES);
+ ;
+
+ if (operation.hasError()) {
+ System.out.printf("Error in creating instance %s", operation.getError());
+ return;
+ }
+
+ System.out.printf("Instance created %s", instanceName);
+ }
+ }
+}
+// [END compute_create_windows_instance_external_ip]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateWindowsServerInstanceInternalIp.java b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateWindowsServerInstanceInternalIp.java
new file mode 100644
index 00000000000..f54e0a2aa1b
--- /dev/null
+++ b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/CreateWindowsServerInstanceInternalIp.java
@@ -0,0 +1,133 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compute.windows.windowsinstances;
+
+// [START compute_create_windows_instance_internal_ip]
+
+import com.google.cloud.compute.v1.AttachedDisk;
+import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
+import com.google.cloud.compute.v1.InsertInstanceRequest;
+import com.google.cloud.compute.v1.Instance;
+import com.google.cloud.compute.v1.InstancesClient;
+import com.google.cloud.compute.v1.NetworkInterface;
+import com.google.cloud.compute.v1.Operation;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class CreateWindowsServerInstanceInternalIp {
+
+ public static void main(String[] args)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // TODO(developer): Replace these variables before running the sample.
+ // projectId - ID or number of the project you want to use.
+ String projectId = "your-google-cloud-project-id";
+
+ // zone - Name of the zone you want to use, for example: us-west3-b
+ String zone = "europe-central2-b";
+
+ // instanceName - Name of the new machine.
+ String instanceName = "instance-name";
+
+ // networkLink - Name of the network you want the new instance to use.
+ // * For example: "global/networks/default" represents the network
+ // * named "default", which is created automatically for each project.
+ String networkLink = "global/networks/default";
+
+ // subnetworkLink - Name of the subnetwork you want the new instance to use.
+ // * This value uses the following format:
+ // * "regions/{region}/subnetworks/{subnetwork_name}"
+ String subnetworkLink = "regions/europe-central2/subnetworks/default";
+
+ createWindowsServerInstanceInternalIp(projectId, zone, instanceName, networkLink,
+ subnetworkLink);
+ }
+
+ // Creates a new Windows Server instance that has only an internal IP address.
+ public static void createWindowsServerInstanceInternalIp(String projectId, String zone,
+ String instanceName, String networkLink, String subnetworkLink)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+
+ // machineType - Machine type you want to create in following format:
+ // * "zones/{zone}/machineTypes/{type_name}". For example:
+ // * "zones/europe-west3-c/machineTypes/f1-micro"
+ // * You can find the list of available machine types using:
+ // * https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
+ String machineType = "n1-standard-1";
+ // sourceImageFamily - Name of the public image family for Windows Server or SQL Server images.
+ // * https://cloud.google.com/compute/docs/images#os-compute-support
+ String sourceImageFamily = "windows-2012-r2";
+
+ // Instantiates a client.
+ try (InstancesClient instancesClient = InstancesClient.create()) {
+
+ AttachedDisk attachedDisk = AttachedDisk.newBuilder()
+ // Describe the size and source image of the boot disk to attach to the instance.
+ .setInitializeParams(AttachedDiskInitializeParams.newBuilder()
+ .setDiskSizeGb(64)
+ .setSourceImage(
+ String.format("projects/windows-cloud/global/images/family/%s",
+ sourceImageFamily))
+ .build())
+ .setAutoDelete(true)
+ .setBoot(true)
+ .setType(AttachedDisk.Type.PERSISTENT.toString())
+ .build();
+
+ Instance instance = Instance.newBuilder()
+ .setName(instanceName)
+ .setMachineType(String.format("zones/%s/machineTypes/%s", zone, machineType))
+ .addDisks(attachedDisk)
+ .addNetworkInterfaces(NetworkInterface.newBuilder()
+ // You must verify or configure routes and firewall rules in your VPC network
+ // to allow access to kms.windows.googlecloud.com.
+ // More information about access to kms.windows.googlecloud.com: https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server
+
+ // Additionally, you must enable Private Google Access for subnets in your VPC network
+ // that contain Windows instances with only internal IP addresses.
+ // More information about Private Google Access: https://cloud.google.com/vpc/docs/configure-private-google-access#enabling
+ .setName(networkLink)
+ .setSubnetwork(subnetworkLink)
+ .build())
+ // If you chose an image that supports Shielded VM, you can optionally change the
+ // instance's Shielded VM settings.
+ // .setShieldedInstanceConfig(ShieldedInstanceConfig.newBuilder()
+ // .setEnableSecureBoot(true)
+ // .setEnableVtpm(true)
+ // .setEnableIntegrityMonitoring(true)
+ // .build())
+ .build();
+
+ InsertInstanceRequest request = InsertInstanceRequest.newBuilder()
+ .setProject(projectId)
+ .setZone(zone)
+ .setInstanceResource(instance)
+ .build();
+
+ // Wait for the operation to complete.
+ Operation operation = instancesClient.insertAsync(request).get(3, TimeUnit.MINUTES);
+ ;
+
+ if (operation.hasError()) {
+ System.out.printf("Error in creating instance %s", operation.getError());
+ return;
+ }
+
+ System.out.printf("Instance created %s", instanceName);
+ }
+ }
+}
+// [END compute_create_windows_instance_internal_ip]
\ No newline at end of file
diff --git a/compute/cloud-client/src/main/java/compute/windows/windowsinstances/GetInstanceSerialPort.java b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/GetInstanceSerialPort.java
new file mode 100644
index 00000000000..6a60d644003
--- /dev/null
+++ b/compute/cloud-client/src/main/java/compute/windows/windowsinstances/GetInstanceSerialPort.java
@@ -0,0 +1,52 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compute.windows.windowsinstances;
+
+// [START compute_get_instance_serial_port]
+
+import com.google.cloud.compute.v1.InstancesClient;
+import com.google.cloud.compute.v1.SerialPortOutput;
+import java.io.IOException;
+
+public class GetInstanceSerialPort {
+
+ public static void main(String[] args) throws IOException {
+ // TODO(developer): Replace these variables before running the sample.
+ // projectId - ID or number of the project you want to use.
+ String projectId = "your-google-cloud-project-id";
+
+ // zone - Name of the zone you want to check, for example: us-west3-b
+ String zone = "europe-central2-b";
+
+ // instanceName - Name of the instance you want to check.
+ String instanceName = "instance-name";
+
+ getInstanceSerialPort(projectId, zone, instanceName);
+ }
+
+ // Prints an instance serial port output.
+ public static void getInstanceSerialPort(String projectId, String zone, String instanceName)
+ throws IOException {
+ // Instantiates a client.
+ try (InstancesClient instancesClient = InstancesClient.create()) {
+
+ SerialPortOutput serialPortOutput = instancesClient.getSerialPortOutput(projectId, zone,
+ instanceName);
+
+ System.out.printf("Output from instance serial port %s", serialPortOutput.getContents());
+ }
+ }
+}
+// [END compute_get_instance_serial_port]
\ No newline at end of file
diff --git a/compute/cloud-client/src/test/java/compute/FirewallIT.java b/compute/cloud-client/src/test/java/compute/FirewallIT.java
new file mode 100644
index 00000000000..6a64961274d
--- /dev/null
+++ b/compute/cloud-client/src/test/java/compute/FirewallIT.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package compute;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.api.gax.rpc.InvalidArgumentException;
+import com.google.api.gax.rpc.NotFoundException;
+import com.google.cloud.compute.v1.FirewallsClient;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.Assert;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
+public class FirewallIT {
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ private static String FIREWALL_RULE_CREATE;
+ private static String NETWORK_NAME;
+
+ private ByteArrayOutputStream stdOut;
+
+ // Check if the required environment variables are set.
+ public static void requireEnvVar(String envVarName) {
+ assertWithMessage(String.format("Missing environment variable '%s' ", envVarName))
+ .that(System.getenv(envVarName)).isNotEmpty();
+ }
+
+ @BeforeAll
+ public static void setUp()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ FIREWALL_RULE_CREATE = "firewall-rule-" + UUID.randomUUID();
+ NETWORK_NAME = "global/networks/default";
+
+ compute.CreateFirewallRule.createFirewall(PROJECT_ID, FIREWALL_RULE_CREATE, NETWORK_NAME);
+ TimeUnit.SECONDS.sleep(10);
+
+ stdOut.close();
+ System.setOut(out);
+ }
+
+
+ @AfterAll
+ public static void cleanup()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ // Delete all instances created for testing.
+ requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ if (!isFirewallRuleDeletedByGceEnforcer(PROJECT_ID, FIREWALL_RULE_CREATE)) {
+ DeleteFirewallRule.deleteFirewallRule(PROJECT_ID, FIREWALL_RULE_CREATE);
+ }
+
+ stdOut.close();
+ System.setOut(out);
+ }
+
+ public static boolean isFirewallRuleDeletedByGceEnforcer(
+ String projectId, String firewallRule)
+ throws IOException {
+ /* (**INTERNAL method**)
+ This method will prevent test failure if the firewall rule was auto-deleted by GCE Enforcer.
+ (Feel free to remove this method if not running on a Google-owned project.)
+ */
+ try {
+ GetFirewallRule.getFirewallRule(projectId, firewallRule);
+ } catch (NotFoundException e) {
+ System.out.println("Rule already deleted! ");
+ return true;
+ } catch (InvalidArgumentException | NullPointerException e) {
+ System.out.println("Rule is not ready (probably being deleted).");
+ return true;
+ }
+ return false;
+ }
+
+ @BeforeEach
+ public void beforeEach() {
+ stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ }
+
+ @AfterEach
+ public void afterEach() {
+ stdOut = null;
+ System.setOut(null);
+ }
+
+ @Test
+ public void testListFirewallRules()
+ throws IOException, ExecutionException, InterruptedException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ if (!isFirewallRuleDeletedByGceEnforcer(PROJECT_ID, FIREWALL_RULE_CREATE)) {
+ compute.ListFirewallRules.listFirewallRules(PROJECT_ID);
+ assertThat(stdOut.toString()).contains(FIREWALL_RULE_CREATE);
+ }
+ // Clear system output to not affect other tests.
+ // Refrain from setting out to null.
+ stdOut.close();
+ System.setOut(out);
+ }
+
+ @Test
+ public void testPatchFirewallRule()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ // Firewall rule is auto-deleted by GCE Enforcer within a few minutes.
+ if (!isFirewallRuleDeletedByGceEnforcer(PROJECT_ID, FIREWALL_RULE_CREATE)) {
+ try (FirewallsClient client = FirewallsClient.create()) {
+ Assert.assertEquals(1000, client.get(PROJECT_ID, FIREWALL_RULE_CREATE).getPriority());
+ compute.PatchFirewallRule.patchFirewallPriority(PROJECT_ID, FIREWALL_RULE_CREATE, 500);
+ TimeUnit.SECONDS.sleep(5);
+ Assert.assertEquals(500, client.get(PROJECT_ID, FIREWALL_RULE_CREATE).getPriority());
+ }
+ }
+ // Clear system output to not affect other tests.
+ // Refrain from setting out to null as it will throw NullPointer in the subsequent tests.
+ stdOut.close();
+ System.setOut(out);
+ }
+
+}
diff --git a/compute/cloud-client/src/test/java/compute/InstanceOperationsIT.java b/compute/cloud-client/src/test/java/compute/InstanceOperationsIT.java
new file mode 100644
index 00000000000..eae0ac8c2ec
--- /dev/null
+++ b/compute/cloud-client/src/test/java/compute/InstanceOperationsIT.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package compute;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.cloud.compute.v1.Instance.Status;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.Assert;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
+public class InstanceOperationsIT {
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ private static String ZONE;
+ private static String MACHINE_NAME;
+ private static String MACHINE_NAME_ENCRYPTED;
+ private static String RAW_KEY;
+
+ private ByteArrayOutputStream stdOut;
+
+ // Check if the required environment variables are set.
+ public static void requireEnvVar(String envVarName) {
+ assertWithMessage(String.format("Missing environment variable '%s' ", envVarName))
+ .that(System.getenv(envVarName)).isNotEmpty();
+ }
+
+ @BeforeAll
+ public static void setUp()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ ZONE = "us-central1-a";
+ MACHINE_NAME = "my-new-test-instance" + UUID.randomUUID();
+ MACHINE_NAME_ENCRYPTED = "encrypted-test-instance" + UUID.randomUUID();
+ RAW_KEY = Util.getBase64EncodedKey();
+
+ // Cleanup existing stale resources.
+ Util.cleanUpExistingInstances("my-new-test-instance", PROJECT_ID, ZONE);
+ Util.cleanUpExistingInstances("encrypted-test-instance", PROJECT_ID, ZONE);
+
+ compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME);
+ compute.CreateEncryptedInstance
+ .createEncryptedInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED, RAW_KEY);
+
+ TimeUnit.SECONDS.sleep(10);
+
+ stdOut.close();
+ System.setOut(out);
+ }
+
+
+ @AfterAll
+ public static void cleanup()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+
+ // Delete all instances created for testing.
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED);
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME);
+
+ stdOut.close();
+ System.setOut(out);
+ }
+
+ @BeforeEach
+ public void beforeEach() {
+ stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ }
+
+ @AfterEach
+ public void afterEach() {
+ stdOut = null;
+ System.setOut(null);
+ }
+
+ @Test
+ public void testInstanceOperations()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ Assert.assertEquals(Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME),
+ Status.RUNNING.toString());
+
+ // Stopping the instance.
+ StopInstance.stopInstance(PROJECT_ID, ZONE, MACHINE_NAME);
+ // Wait for the operation to complete. Setting timeout to 3 mins.
+ LocalDateTime endTime = LocalDateTime.now().plusMinutes(3);
+ while (!Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME)
+ .equalsIgnoreCase(Status.STOPPED.toString())
+ && LocalDateTime.now().isBefore(endTime)) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+ Assert.assertEquals(Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME),
+ Status.TERMINATED.toString());
+
+ // Starting the instance.
+ StartInstance.startInstance(PROJECT_ID, ZONE, MACHINE_NAME);
+ // Wait for the operation to complete. Setting timeout to 3 mins.
+ endTime = LocalDateTime.now().plusMinutes(3);
+ while (!Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME)
+ .equalsIgnoreCase(Status.RUNNING.toString())
+ && LocalDateTime.now().isBefore(endTime)) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+ Assert.assertEquals(Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME),
+ Status.RUNNING.toString());
+ }
+
+ @Test
+ public void testEncryptedInstanceOperations()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ Assert.assertEquals(Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED),
+ Status.RUNNING.toString());
+
+ // Stopping the encrypted instance.
+ StopInstance.stopInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED);
+ // Wait for the operation to complete. Setting timeout to 3 mins.
+ LocalDateTime endTime = LocalDateTime.now().plusMinutes(3);
+ while (!Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED)
+ .equalsIgnoreCase(Status.STOPPED.toString())
+ && LocalDateTime.now().isBefore(endTime)) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+ Assert.assertEquals(Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED),
+ Status.TERMINATED.toString());
+
+ // Starting the encrypted instance.
+ StartEncryptedInstance
+ .startEncryptedInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED, RAW_KEY);
+ // Wait for the operation to complete. Setting timeout to 3 mins.
+ endTime = LocalDateTime.now().plusMinutes(3);
+ while (!Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED)
+ .equalsIgnoreCase(Status.RUNNING.toString())
+ && LocalDateTime.now().isBefore(endTime)) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+ Assert.assertEquals(Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED),
+ Status.RUNNING.toString());
+ }
+}
diff --git a/compute/cloud-client/src/test/java/compute/InstanceTemplatesIT.java b/compute/cloud-client/src/test/java/compute/InstanceTemplatesIT.java
index 0fb8b4bef49..6bef26c0c06 100644
--- a/compute/cloud-client/src/test/java/compute/InstanceTemplatesIT.java
+++ b/compute/cloud-client/src/test/java/compute/InstanceTemplatesIT.java
@@ -27,19 +27,21 @@
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import org.junit.After;
-import org.junit.AfterClass;
+import java.util.concurrent.TimeoutException;
import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
public class InstanceTemplatesIT {
-
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
private static final String DEFAULT_REGION = "us-central1";
private static final String DEFAULT_ZONE = DEFAULT_REGION + "-a";
@@ -59,8 +61,10 @@ public static void requireEnvVar(String envVarName) {
.that(System.getenv(envVarName)).isNotEmpty();
}
- @BeforeClass
- public static void setup() throws IOException, ExecutionException, InterruptedException {
+ @BeforeAll
+ public static void setup()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
@@ -113,11 +117,13 @@ public static void setup() throws IOException, ExecutionException, InterruptedEx
Assert.assertEquals(
getInstance(DEFAULT_ZONE, MACHINE_NAME_CR_TEMPLATE_OR).getDisksCount(), 2);
stdOut.close();
- System.setOut(null);
+ System.setOut(out);
}
- @AfterClass
- public static void cleanup() throws IOException, ExecutionException, InterruptedException {
+ @AfterAll
+ public static void cleanup()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
// Delete instances.
@@ -135,7 +141,7 @@ public static void cleanup() throws IOException, ExecutionException, Interrupted
assertThat(stdOut.toString())
.contains("Instance template deletion operation status for " + TEMPLATE_NAME_WITH_SUBNET);
stdOut.close();
- System.setOut(null);
+ System.setOut(out);
}
public static Instance getInstance(String zone, String instanceName) throws IOException {
@@ -144,13 +150,13 @@ public static Instance getInstance(String zone, String instanceName) throws IOEx
}
}
- @Before
+ @BeforeEach
public void beforeEach() {
stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
}
- @After
+ @AfterEach
public void afterEach() {
stdOut = null;
System.setOut(null);
diff --git a/compute/cloud-client/src/test/java/compute/InstancesAdvancedIT.java b/compute/cloud-client/src/test/java/compute/InstancesAdvancedIT.java
new file mode 100644
index 00000000000..cd0552603f7
--- /dev/null
+++ b/compute/cloud-client/src/test/java/compute/InstancesAdvancedIT.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package compute;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.api.gax.longrunning.OperationFuture;
+import com.google.cloud.compute.v1.Disk;
+import com.google.cloud.compute.v1.DisksClient;
+import com.google.cloud.compute.v1.Image;
+import com.google.cloud.compute.v1.ImagesClient;
+import com.google.cloud.compute.v1.Instance.Status;
+import com.google.cloud.compute.v1.Operation;
+import com.google.cloud.compute.v1.Snapshot;
+import com.google.cloud.compute.v1.SnapshotsClient;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.Assert;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
+public class InstancesAdvancedIT {
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ private static String ZONE;
+ private static String MACHINE_NAME_PUBLIC_IMAGE;
+ private static String MACHINE_NAME_CUSTOM_IMAGE;
+ private static String MACHINE_NAME_ADDITIONAL_DISK;
+ private static String MACHINE_NAME_SNAPSHOT;
+ private static String MACHINE_NAME_SNAPSHOT_ADDITIONAL;
+ private static String MACHINE_NAME_SUBNETWORK;
+ private static Disk TEST_DISK;
+ private static Image TEST_IMAGE;
+ private static Snapshot TEST_SNAPSHOT;
+ private static String NETWORK_NAME;
+ private static String SUBNETWORK_NAME;
+
+ private ByteArrayOutputStream stdOut;
+
+ // Check if the required environment variables are set.
+ public static void requireEnvVar(String envVarName) {
+ assertWithMessage(String.format("Missing environment variable '%s' ", envVarName))
+ .that(System.getenv(envVarName)).isNotEmpty();
+ }
+
+ @BeforeAll
+ public static void setup()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ ZONE = "us-central1-a";
+ MACHINE_NAME_PUBLIC_IMAGE = "test-instance-pub-" + UUID.randomUUID();
+ MACHINE_NAME_CUSTOM_IMAGE = "test-instance-cust-" + UUID.randomUUID();
+ MACHINE_NAME_ADDITIONAL_DISK = "test-instance-add-" + UUID.randomUUID();
+ MACHINE_NAME_SNAPSHOT = "test-instance-snap-" + UUID.randomUUID();
+ MACHINE_NAME_SNAPSHOT_ADDITIONAL = "test-instance-snapa-" + UUID.randomUUID();
+ MACHINE_NAME_SUBNETWORK = "test-instance-subnet-" + UUID.randomUUID();
+ NETWORK_NAME = "global/networks/default";
+ SUBNETWORK_NAME = "regions/us-central1/subnetworks/default";
+
+ TEST_DISK = createSourceDisk();
+ TEST_SNAPSHOT = createSnapshot(TEST_DISK);
+ TEST_IMAGE = createImage(TEST_DISK);
+
+ Util.cleanUpExistingInstances("test-instance", PROJECT_ID, ZONE);
+
+ compute.CreateInstancesAdvanced.createFromPublicImage(PROJECT_ID, ZONE,
+ MACHINE_NAME_PUBLIC_IMAGE);
+ compute.CreateInstancesAdvanced.createFromCustomImage(PROJECT_ID, ZONE,
+ MACHINE_NAME_CUSTOM_IMAGE, TEST_IMAGE.getSelfLink());
+ compute.CreateInstancesAdvanced.createWithAdditionalDisk(PROJECT_ID, ZONE,
+ MACHINE_NAME_ADDITIONAL_DISK);
+ compute.CreateInstancesAdvanced.createFromSnapshot(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT,
+ TEST_SNAPSHOT.getSelfLink());
+ compute.CreateInstancesAdvanced.createWithSnapshottedDataDisk(PROJECT_ID, ZONE,
+ MACHINE_NAME_SNAPSHOT_ADDITIONAL, TEST_SNAPSHOT.getSelfLink());
+ compute.CreateInstancesAdvanced.createWithSubnetwork(PROJECT_ID, ZONE, MACHINE_NAME_SUBNETWORK,
+ NETWORK_NAME, SUBNETWORK_NAME);
+
+ TimeUnit.SECONDS.sleep(10);
+ stdOut.close();
+ System.setOut(out);
+ }
+
+ @AfterAll
+ public static void cleanup()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ // Delete all instances created for testing.
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_PUBLIC_IMAGE);
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_CUSTOM_IMAGE);
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_ADDITIONAL_DISK);
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT);
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT_ADDITIONAL);
+ compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_SUBNETWORK);
+
+ deleteImage(TEST_IMAGE);
+ deleteSnapshot(TEST_SNAPSHOT);
+ deleteDisk(TEST_DISK);
+
+ stdOut.close();
+ System.setOut(out);
+ }
+
+ private static Image getActiveDebian()
+ throws IOException {
+ try (ImagesClient imagesClient = ImagesClient.create()) {
+ return imagesClient.getFromFamily("debian-cloud", "debian-11");
+ }
+ }
+
+ private static Disk createSourceDisk()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ try (DisksClient disksClient = DisksClient.create()) {
+
+ Disk disk = Disk.newBuilder()
+ .setSourceImage(getActiveDebian().getSelfLink())
+ .setName("test-disk-" + UUID.randomUUID())
+ .build();
+
+ OperationFuture operation = disksClient.insertAsync(PROJECT_ID, ZONE,
+ disk);
+ // Wait for the operation to complete.
+ operation.get(3, TimeUnit.MINUTES);
+ return disksClient.get(PROJECT_ID, ZONE, disk.getName());
+ }
+ }
+
+ private static void deleteDisk(Disk disk)
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ try (DisksClient disksClient = DisksClient.create()) {
+ OperationFuture operation = disksClient.deleteAsync(PROJECT_ID, ZONE,
+ disk.getName());
+ operation.get(3, TimeUnit.MINUTES);
+ }
+ }
+
+ private static Snapshot createSnapshot(Disk srcDisk)
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ try (SnapshotsClient snapshotsClient = SnapshotsClient.create();
+ DisksClient disksClient = DisksClient.create()) {
+
+ Snapshot snapshot = Snapshot.newBuilder()
+ .setName("test-snap-" + UUID.randomUUID())
+ .build();
+
+ OperationFuture operation = disksClient.createSnapshotAsync(PROJECT_ID,
+ ZONE, srcDisk.getName(),
+ snapshot);
+ operation.get(3, TimeUnit.MINUTES);
+ return snapshotsClient.get(PROJECT_ID, snapshot.getName());
+ }
+ }
+
+ private static void deleteSnapshot(Snapshot snapshot)
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ try (SnapshotsClient snapshotsClient = SnapshotsClient.create()) {
+ OperationFuture operation = snapshotsClient.deleteAsync(PROJECT_ID,
+ snapshot.getName());
+ operation.get(3, TimeUnit.MINUTES);
+ }
+ }
+
+ private static Image createImage(Disk srcDisk)
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ try (ImagesClient imagesClient = ImagesClient.create()) {
+
+ Image image = Image.newBuilder()
+ .setName("test-img-" + UUID.randomUUID())
+ .setSourceDisk(srcDisk.getSelfLink())
+ .build();
+
+ OperationFuture operation = imagesClient.insertAsync(PROJECT_ID, image);
+ operation.get(3, TimeUnit.MINUTES);
+ return imagesClient.get(PROJECT_ID, image.getName());
+ }
+ }
+
+ private static void deleteImage(Image image)
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ try (ImagesClient imagesClient = ImagesClient.create()) {
+ OperationFuture operation = imagesClient.deleteAsync(PROJECT_ID,
+ image.getName());
+ operation.get(3, TimeUnit.MINUTES);
+ }
+ }
+
+
+ @BeforeEach
+ public void beforeEach() {
+ stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ }
+
+ @AfterEach
+ public void afterEach() {
+ stdOut = null;
+ System.setOut(null);
+ }
+
+ @Test
+ public void testCreatePublicImage() throws IOException {
+ // Check if the instance was successfully created during the setup.
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_PUBLIC_IMAGE);
+ Assert.assertEquals(response, Status.RUNNING.toString());
+ }
+
+ @Test
+ public void testCreateCustomImage() throws IOException {
+ // Check if the instance was successfully created during the setup.
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_CUSTOM_IMAGE);
+ Assert.assertEquals(response, Status.RUNNING.toString());
+ }
+
+ @Test
+ public void testCreateAdditionalDisk() throws IOException {
+ // Check if the instance was successfully created during the setup.
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ADDITIONAL_DISK);
+ Assert.assertEquals(response, Status.RUNNING.toString());
+ }
+
+ @Test
+ public void testCreateFromSnapshot() throws IOException {
+ // Check if the instance was successfully created during the setup.
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT);
+ Assert.assertEquals(response, Status.RUNNING.toString());
+ }
+
+ @Test
+ public void testCreateFromSnapshotAdditional() throws IOException {
+ // Check if the instance was successfully created during the setup.
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT_ADDITIONAL);
+ Assert.assertEquals(response, Status.RUNNING.toString());
+ }
+
+ @Test
+ public void testCreateInSubnetwork() throws IOException {
+ // Check if the instance was successfully created during the setup.
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_SUBNETWORK);
+ Assert.assertEquals(response, Status.RUNNING.toString());
+ }
+
+}
diff --git a/compute/cloud-client/src/test/java/compute/SnippetsIT.java b/compute/cloud-client/src/test/java/compute/SnippetsIT.java
index af353c65662..9c0a0f1dd2b 100644
--- a/compute/cloud-client/src/test/java/compute/SnippetsIT.java
+++ b/compute/cloud-client/src/test/java/compute/SnippetsIT.java
@@ -20,19 +20,9 @@
import static com.google.common.truth.Truth.assertWithMessage;
import com.google.api.gax.longrunning.OperationFuture;
-import com.google.api.gax.rpc.InvalidArgumentException;
-import com.google.api.gax.rpc.NotFoundException;
-import com.google.cloud.compute.v1.Disk;
-import com.google.cloud.compute.v1.DisksClient;
-import com.google.cloud.compute.v1.FirewallsClient;
-import com.google.cloud.compute.v1.Image;
-import com.google.cloud.compute.v1.ImagesClient;
-import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.Instance.Status;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
-import com.google.cloud.compute.v1.Snapshot;
-import com.google.cloud.compute.v1.SnapshotsClient;
import com.google.cloud.compute.v1.UsageExportLocation;
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.BucketInfo;
@@ -41,48 +31,33 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
-import java.nio.charset.StandardCharsets;
-import java.security.SecureRandom;
-import java.time.LocalDateTime;
-import java.util.Base64;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import java.util.stream.IntStream;
-import org.junit.After;
-import org.junit.AfterClass;
+import java.util.concurrent.TimeoutException;
import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
public class SnippetsIT {
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
private static String ZONE;
private static String MACHINE_NAME;
- private static String MACHINE_NAME_DELETE;
private static String MACHINE_NAME_LIST_INSTANCE;
private static String MACHINE_NAME_WAIT_FOR_OP;
private static String MACHINE_NAME_ENCRYPTED;
- private static String MACHINE_NAME_PUBLIC_IMAGE;
- private static String MACHINE_NAME_CUSTOM_IMAGE;
- private static String MACHINE_NAME_ADDITIONAL_DISK;
- private static String MACHINE_NAME_SNAPSHOT;
- private static String MACHINE_NAME_SNAPSHOT_ADDITIONAL;
- private static String MACHINE_NAME_SUBNETWORK;
private static String BUCKET_NAME;
private static String IMAGE_PROJECT_NAME;
- private static String FIREWALL_RULE_CREATE;
- private static String NETWORK_NAME;
- private static String SUBNETWORK_NAME;
private static String RAW_KEY;
- private static Disk TEST_DISK;
- private static Image TEST_IMAGE;
- private static Snapshot TEST_SNAPSHOT;
private ByteArrayOutputStream stdOut;
@@ -92,8 +67,10 @@ public static void requireEnvVar(String envVarName) {
.that(System.getenv(envVarName)).isNotEmpty();
}
- @BeforeClass
- public static void setUp() throws IOException, InterruptedException, ExecutionException {
+ @BeforeAll
+ public static void setUp()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
@@ -101,22 +78,12 @@ public static void setUp() throws IOException, InterruptedException, ExecutionEx
ZONE = "us-central1-a";
MACHINE_NAME = "my-new-test-instance" + UUID.randomUUID();
- MACHINE_NAME_DELETE = "my-new-test-instance" + UUID.randomUUID();
MACHINE_NAME_LIST_INSTANCE = "my-new-test-instance" + UUID.randomUUID();
MACHINE_NAME_WAIT_FOR_OP = "my-new-test-instance" + UUID.randomUUID();
MACHINE_NAME_ENCRYPTED = "encrypted-test-instance" + UUID.randomUUID();
- MACHINE_NAME_PUBLIC_IMAGE = "test-instance-pub-" + UUID.randomUUID();
- MACHINE_NAME_CUSTOM_IMAGE = "test-instance-cust-" + UUID.randomUUID();
- MACHINE_NAME_ADDITIONAL_DISK = "test-instance-add-" + UUID.randomUUID();
- MACHINE_NAME_SNAPSHOT = "test-instance-snap-" + UUID.randomUUID();
- MACHINE_NAME_SNAPSHOT_ADDITIONAL = "test-instance-snapa-" + UUID.randomUUID();
- MACHINE_NAME_SUBNETWORK = "test-instance-subnet-" + UUID.randomUUID();
BUCKET_NAME = "my-new-test-bucket" + UUID.randomUUID();
IMAGE_PROJECT_NAME = "windows-sql-cloud";
- FIREWALL_RULE_CREATE = "firewall-rule-" + UUID.randomUUID();
- NETWORK_NAME = "global/networks/default";
- SUBNETWORK_NAME = "regions/us-central1/subnetworks/default";
- RAW_KEY = getBase64EncodedKey();
+ RAW_KEY = Util.getBase64EncodedKey();
// Cleanup existing stale resources.
Util.cleanUpExistingInstances("my-new-test-instance", PROJECT_ID, ZONE);
@@ -124,242 +91,53 @@ public static void setUp() throws IOException, InterruptedException, ExecutionEx
Util.cleanUpExistingInstances("test-instance-", PROJECT_ID, ZONE);
compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME);
- compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME_DELETE);
compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME_LIST_INSTANCE);
compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME_WAIT_FOR_OP);
compute.CreateEncryptedInstance
.createEncryptedInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED, RAW_KEY);
- TEST_DISK = createSourceDisk();
- TEST_SNAPSHOT = createSnapshot(TEST_DISK);
- TEST_IMAGE = createImage(TEST_DISK);
-
- compute.CreateInstancesAdvanced.createFromPublicImage(PROJECT_ID, ZONE,
- MACHINE_NAME_PUBLIC_IMAGE);
- compute.CreateInstancesAdvanced.createFromCustomImage(PROJECT_ID, ZONE,
- MACHINE_NAME_CUSTOM_IMAGE, TEST_IMAGE.getSelfLink());
- compute.CreateInstancesAdvanced.createWithAdditionalDisk(PROJECT_ID, ZONE,
- MACHINE_NAME_ADDITIONAL_DISK);
- compute.CreateInstancesAdvanced.createFromSnapshot(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT,
- TEST_SNAPSHOT.getSelfLink());
- compute.CreateInstancesAdvanced.createWithSnapshottedDataDisk(PROJECT_ID, ZONE,
- MACHINE_NAME_SNAPSHOT_ADDITIONAL, TEST_SNAPSHOT.getSelfLink());
- compute.CreateInstancesAdvanced.createWithSubnetwork(PROJECT_ID, ZONE, MACHINE_NAME_SUBNETWORK,
- NETWORK_NAME, SUBNETWORK_NAME);
-
- TimeUnit.SECONDS.sleep(10);
- compute.CreateFirewallRule.createFirewall(PROJECT_ID, FIREWALL_RULE_CREATE, NETWORK_NAME);
TimeUnit.SECONDS.sleep(10);
- // Moving the following tests to setup section as the created firewall rule is auto-deleted
- // by GCE Enforcer within a few minutes.
- testListFirewallRules();
- testPatchFirewallRule();
// Create a Google Cloud Storage bucket for UsageReports
Storage storage = StorageOptions.newBuilder().setProjectId(PROJECT_ID).build().getService();
storage.create(BucketInfo.of(BUCKET_NAME));
stdOut.close();
- System.setOut(null);
+ System.setOut(out);
}
- @AfterClass
- public static void cleanup() throws IOException, InterruptedException, ExecutionException {
+ @AfterAll
+ public static void cleanup()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
// Delete all instances created for testing.
requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
requireEnvVar("GOOGLE_CLOUD_PROJECT");
- if (!isFirewallRuleDeletedByGceEnforcer(PROJECT_ID, FIREWALL_RULE_CREATE)) {
- DeleteFirewallRule.deleteFirewallRule(PROJECT_ID, FIREWALL_RULE_CREATE);
- }
compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED);
compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME);
compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_LIST_INSTANCE);
- compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_PUBLIC_IMAGE);
- compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_CUSTOM_IMAGE);
- compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_ADDITIONAL_DISK);
- compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT);
- compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_SNAPSHOT_ADDITIONAL);
- compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_SUBNETWORK);
-
- deleteImage(TEST_IMAGE);
- deleteSnapshot(TEST_SNAPSHOT);
- deleteDisk(TEST_DISK);
-
// Delete the Google Cloud Storage bucket created for usage reports.
Storage storage = StorageOptions.newBuilder().setProjectId(PROJECT_ID).build().getService();
Bucket bucket = storage.get(BUCKET_NAME);
bucket.delete();
- stdOut.close();
- System.setOut(null);
- }
-
- private static Image getActiveDebian()
- throws IOException {
- try (ImagesClient imagesClient = ImagesClient.create()) {
- return imagesClient.getFromFamily("debian-cloud", "debian-11");
- }
- }
-
- private static Disk createSourceDisk()
- throws IOException, ExecutionException, InterruptedException {
- try (DisksClient disksClient = DisksClient.create()) {
-
- Disk disk = Disk.newBuilder()
- .setSourceImage(getActiveDebian().getSelfLink())
- .setName("test-disk-" + UUID.randomUUID())
- .build();
-
- OperationFuture operation = disksClient.insertAsync(PROJECT_ID, ZONE,
- disk);
- // Wait for the operation to complete.
- operation.get();
- return disksClient.get(PROJECT_ID, ZONE, disk.getName());
- }
- }
-
- private static void deleteDisk(Disk disk)
- throws IOException, InterruptedException, ExecutionException {
- try (DisksClient disksClient = DisksClient.create()) {
- OperationFuture operation = disksClient.deleteAsync(PROJECT_ID, ZONE,
- disk.getName());
- operation.get();
- }
- }
-
- private static Snapshot createSnapshot(Disk srcDisk)
- throws IOException, InterruptedException, ExecutionException {
- try (SnapshotsClient snapshotsClient = SnapshotsClient.create();
- DisksClient disksClient = DisksClient.create()) {
-
- Snapshot snapshot = Snapshot.newBuilder()
- .setName("test-snap-" + UUID.randomUUID())
- .build();
-
- OperationFuture operation = disksClient.createSnapshotAsync(PROJECT_ID,
- ZONE, srcDisk.getName(),
- snapshot);
- operation.get();
- return snapshotsClient.get(PROJECT_ID, snapshot.getName());
- }
- }
-
- private static void deleteSnapshot(Snapshot snapshot)
- throws IOException, InterruptedException, ExecutionException {
- try (SnapshotsClient snapshotsClient = SnapshotsClient.create()) {
- OperationFuture operation = snapshotsClient.deleteAsync(PROJECT_ID,
- snapshot.getName());
- operation.get();
- }
- }
-
- private static Image createImage(Disk srcDisk)
- throws IOException, InterruptedException, ExecutionException {
- try (ImagesClient imagesClient = ImagesClient.create()) {
-
- Image image = Image.newBuilder()
- .setName("test-img-" + UUID.randomUUID())
- .setSourceDisk(srcDisk.getSelfLink())
- .build();
-
- OperationFuture operation = imagesClient.insertAsync(PROJECT_ID, image);
- operation.get();
- return imagesClient.get(PROJECT_ID, image.getName());
- }
- }
-
- private static void deleteImage(Image image)
- throws IOException, InterruptedException, ExecutionException {
- try (ImagesClient imagesClient = ImagesClient.create()) {
- OperationFuture operation = imagesClient.deleteAsync(PROJECT_ID,
- image.getName());
- operation.get();
- }
- }
-
- public static String getBase64EncodedKey() {
- String sampleSpace = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- StringBuilder stringBuilder = new StringBuilder();
- SecureRandom random = new SecureRandom();
- IntStream.range(0, 32)
- .forEach(
- x -> stringBuilder.append(sampleSpace.charAt(random.nextInt(sampleSpace.length()))));
-
- return Base64.getEncoder()
- .encodeToString(stringBuilder.toString().getBytes(StandardCharsets.US_ASCII));
- }
-
- public static void testListFirewallRules()
- throws IOException, ExecutionException, InterruptedException {
- final PrintStream out = System.out;
- ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
- System.setOut(new PrintStream(stdOut));
- if (!isFirewallRuleDeletedByGceEnforcer(PROJECT_ID, FIREWALL_RULE_CREATE)) {
- compute.ListFirewallRules.listFirewallRules(PROJECT_ID);
- assertThat(stdOut.toString()).contains(FIREWALL_RULE_CREATE);
- }
- // Clear system output to not affect other tests.
- // Refrain from setting out to null.
- stdOut.close();
- System.setOut(out);
- }
-
- public static void testPatchFirewallRule()
- throws IOException, InterruptedException, ExecutionException {
- final PrintStream out = System.out;
- ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
- System.setOut(new PrintStream(stdOut));
- if (!isFirewallRuleDeletedByGceEnforcer(PROJECT_ID, FIREWALL_RULE_CREATE)) {
- try (FirewallsClient client = FirewallsClient.create()) {
- Assert.assertEquals(1000, client.get(PROJECT_ID, FIREWALL_RULE_CREATE).getPriority());
- compute.PatchFirewallRule.patchFirewallPriority(PROJECT_ID, FIREWALL_RULE_CREATE, 500);
- TimeUnit.SECONDS.sleep(5);
- Assert.assertEquals(500, client.get(PROJECT_ID, FIREWALL_RULE_CREATE).getPriority());
- }
- }
- // Clear system output to not affect other tests.
- // Refrain from setting out to null as it will throw NullPointer in the subsequent tests.
stdOut.close();
System.setOut(out);
}
- public static boolean isFirewallRuleDeletedByGceEnforcer(String projectId,
- String firewallRule) throws IOException, ExecutionException, InterruptedException {
- /* (**INTERNAL method**)
- This method will prevent test failure if the firewall rule was auto-deleted by GCE Enforcer.
- (Feel free to remove this method if not running on a Google-owned project.)
- */
- try {
- GetFirewallRule.getFirewallRule(projectId, firewallRule);
- } catch (NotFoundException e) {
- System.out.println("Rule already deleted ! ");
- return true;
- } catch (InvalidArgumentException | NullPointerException e) {
- System.out.println("Rule is not ready (probably being deleted).");
- return true;
- }
- return false;
- }
-
- public static String getInstanceStatus(String instanceName) throws IOException {
- try (InstancesClient instancesClient = InstancesClient.create()) {
- Instance response = instancesClient.get(PROJECT_ID, ZONE, instanceName);
- return response.getStatus();
- }
- }
- @Before
+ @BeforeEach
public void beforeEach() {
stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
}
- @After
+ @AfterEach
public void afterEach() {
stdOut = null;
System.setOut(null);
@@ -368,58 +146,17 @@ public void afterEach() {
@Test
public void testCreateInstance() throws IOException {
// Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME);
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME);
Assert.assertEquals(response, Status.RUNNING.toString());
}
@Test
public void testCreateEncryptedInstance() throws IOException {
// Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME_ENCRYPTED);
+ String response = Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED);
Assert.assertEquals(response, Status.RUNNING.toString());
}
- @Test
- public void testCreatePublicImage() throws IOException {
- // Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME_PUBLIC_IMAGE);
- Assert.assertEquals(response, Status.RUNNING.toString());
- }
-
- @Test
- public void testCreateCustomImage() throws IOException {
- // Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME_CUSTOM_IMAGE);
- Assert.assertEquals(response, Status.RUNNING.toString());
- }
-
- @Test
- public void testCreateAdditionalDisk() throws IOException {
- // Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME_ADDITIONAL_DISK);
- Assert.assertEquals(response, Status.RUNNING.toString());
- }
-
- @Test
- public void testCreateFromSnapshot() throws IOException {
- // Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME_SNAPSHOT);
- Assert.assertEquals(response, Status.RUNNING.toString());
- }
-
- @Test
- public void testCreateFromSnapshotAdditional() throws IOException {
- // Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME_SNAPSHOT_ADDITIONAL);
- Assert.assertEquals(response, Status.RUNNING.toString());
- }
-
- @Test
- public void testCreateInSubnetwork() throws IOException {
- // Check if the instance was successfully created during the setup.
- String response = getInstanceStatus(MACHINE_NAME_SUBNETWORK);
- Assert.assertEquals(response, Status.RUNNING.toString());
- }
@Test
public void testListInstance() throws IOException {
@@ -434,25 +171,20 @@ public void testListAllInstances() throws IOException {
}
@Test
- public void testDeleteInstance() throws IOException, InterruptedException, ExecutionException {
- compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_DELETE);
- assertThat(stdOut.toString()).contains("Operation Status: DONE");
- }
-
- @Test
- public void testWaitForOperation() throws IOException, InterruptedException, ExecutionException {
+ public void testWaitForOperation()
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// Construct a delete request and get the operation instance.
InstancesClient instancesClient = InstancesClient.create();
OperationFuture operation = instancesClient.deleteAsync(PROJECT_ID, ZONE,
MACHINE_NAME_WAIT_FOR_OP);
// Wait for the operation to complete.
- operation.get();
+ operation.get(3, TimeUnit.MINUTES);
assertThat(stdOut.toString().contains("Operation Status: DONE"));
}
@Test
public void testSetUsageBucketExportCustomPrefix()
- throws IOException, InterruptedException, ExecutionException {
+ throws IOException, InterruptedException, ExecutionException, TimeoutException {
// Set custom Report Name Prefix.
String customPrefix = "my-custom-prefix";
compute.SetUsageExportBucket.setUsageExportBucket(PROJECT_ID, BUCKET_NAME, customPrefix);
@@ -488,57 +220,4 @@ public void testListImagesByPage() throws IOException {
Assert.assertTrue(stdOut.toString().contains("Page Number: 1"));
}
- @Test
- public void testInstanceOperations()
- throws IOException, ExecutionException, InterruptedException {
- Assert.assertEquals(getInstanceStatus(MACHINE_NAME), Status.RUNNING.toString());
-
- // Stopping the instance.
- StopInstance.stopInstance(PROJECT_ID, ZONE, MACHINE_NAME);
- // Wait for the operation to complete. Setting timeout to 3 mins.
- LocalDateTime endTime = LocalDateTime.now().plusMinutes(3);
- while (getInstanceStatus(MACHINE_NAME).equalsIgnoreCase(Status.STOPPING.toString())
- && LocalDateTime.now().isBefore(endTime)) {
- TimeUnit.SECONDS.sleep(5);
- }
- Assert.assertEquals(getInstanceStatus(MACHINE_NAME), Status.TERMINATED.toString());
-
- // Starting the instance.
- StartInstance.startInstance(PROJECT_ID, ZONE, MACHINE_NAME);
- // Wait for the operation to complete. Setting timeout to 3 mins.
- endTime = LocalDateTime.now().plusMinutes(3);
- while (getInstanceStatus(MACHINE_NAME).equalsIgnoreCase(Status.RUNNING.toString())
- && LocalDateTime.now().isBefore(endTime)) {
- TimeUnit.SECONDS.sleep(5);
- }
- Assert.assertEquals(getInstanceStatus(MACHINE_NAME), Status.RUNNING.toString());
- }
-
- @Test
- public void testEncryptedInstanceOperations()
- throws IOException, ExecutionException, InterruptedException {
- Assert.assertEquals(getInstanceStatus(MACHINE_NAME_ENCRYPTED), Status.RUNNING.toString());
-
- // Stopping the encrypted instance.
- StopInstance.stopInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED);
- // Wait for the operation to complete. Setting timeout to 3 mins.
- LocalDateTime endTime = LocalDateTime.now().plusMinutes(3);
- while (getInstanceStatus(MACHINE_NAME_ENCRYPTED).equalsIgnoreCase(Status.STOPPING.toString())
- && LocalDateTime.now().isBefore(endTime)) {
- TimeUnit.SECONDS.sleep(5);
- }
- Assert.assertEquals(getInstanceStatus(MACHINE_NAME_ENCRYPTED), Status.TERMINATED.toString());
-
- // Starting the encrypted instance.
- StartEncryptedInstance
- .startEncryptedInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED, RAW_KEY);
- // Wait for the operation to complete. Setting timeout to 3 mins.
- endTime = LocalDateTime.now().plusMinutes(3);
- while (getInstanceStatus(MACHINE_NAME_ENCRYPTED).equalsIgnoreCase(Status.RUNNING.toString())
- && LocalDateTime.now().isBefore(endTime)) {
- TimeUnit.SECONDS.sleep(5);
- }
- Assert.assertEquals(getInstanceStatus(MACHINE_NAME_ENCRYPTED), Status.RUNNING.toString());
- }
-
}
diff --git a/compute/cloud-client/src/test/java/compute/Util.java b/compute/cloud-client/src/test/java/compute/Util.java
index f68cca0f0ce..cf0adb0de7e 100644
--- a/compute/cloud-client/src/test/java/compute/Util.java
+++ b/compute/cloud-client/src/test/java/compute/Util.java
@@ -16,15 +16,27 @@
package compute;
+import com.google.cloud.compute.v1.AggregatedListInstancesRequest;
import com.google.cloud.compute.v1.Instance;
+import com.google.cloud.compute.v1.Instance.Status;
import com.google.cloud.compute.v1.InstanceTemplate;
+import com.google.cloud.compute.v1.InstanceTemplatesClient;
+import com.google.cloud.compute.v1.InstanceTemplatesClient.ListPagedResponse;
+import com.google.cloud.compute.v1.InstancesClient;
+import com.google.cloud.compute.v1.InstancesClient.AggregatedListPagedResponse;
import com.google.cloud.compute.v1.InstancesScopedList;
+import com.google.cloud.compute.v1.ListInstanceTemplatesRequest;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
+import java.util.Base64;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.IntStream;
public class Util {
// Cleans existing test resources if any.
@@ -36,14 +48,15 @@ public class Util {
// Delete templates which starts with the given prefixToDelete and
// has creation timestamp >24 hours.
public static void cleanUpExistingInstanceTemplates(String prefixToDelete, String projectId)
- throws IOException, ExecutionException, InterruptedException {
- for (InstanceTemplate template : ListInstanceTemplates.listInstanceTemplates(projectId)
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ for (InstanceTemplate template : listFilteredInstanceTemplates(projectId, prefixToDelete)
.iterateAll()) {
if (!template.hasCreationTimestamp()) {
continue;
}
if (template.getName().contains(prefixToDelete)
- && isCreatedBeforeThresholdTime(template.getCreationTimestamp())) {
+ && isCreatedBeforeThresholdTime(template.getCreationTimestamp())
+ && template.isInitialized()) {
DeleteInstanceTemplate.deleteInstanceTemplate(projectId, template.getName());
}
}
@@ -54,15 +67,16 @@ && isCreatedBeforeThresholdTime(template.getCreationTimestamp())) {
// has creation timestamp >24 hours.
public static void cleanUpExistingInstances(String prefixToDelete, String projectId,
String instanceZone)
- throws IOException, ExecutionException, InterruptedException {
- for (Entry instanceGroup : ListAllInstances.listAllInstances(
- projectId).iterateAll()) {
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ for (Entry instanceGroup : listFilteredInstances(
+ projectId, prefixToDelete).iterateAll()) {
for (Instance instance : instanceGroup.getValue().getInstancesList()) {
if (!instance.hasCreationTimestamp()) {
continue;
}
if (instance.getName().contains(prefixToDelete)
- && isCreatedBeforeThresholdTime(instance.getCreationTimestamp())) {
+ && isCreatedBeforeThresholdTime(instance.getCreationTimestamp())
+ && instance.getStatus().equalsIgnoreCase(Status.RUNNING.toString())) {
DeleteInstance.deleteInstance(projectId, instanceZone, instance.getName());
}
}
@@ -74,4 +88,52 @@ public static boolean isCreatedBeforeThresholdTime(String timestamp) {
.isBefore(Instant.now().minus(DELETION_THRESHOLD_TIME_HOURS, ChronoUnit.HOURS));
}
+ public static AggregatedListPagedResponse listFilteredInstances(String project,
+ String instanceNamePrefix) throws IOException {
+ try (InstancesClient instancesClient = InstancesClient.create()) {
+
+ AggregatedListInstancesRequest aggregatedListInstancesRequest = AggregatedListInstancesRequest
+ .newBuilder()
+ .setProject(project)
+ .setFilter(String.format("name:%s", instanceNamePrefix))
+ .build();
+
+ return instancesClient
+ .aggregatedList(aggregatedListInstancesRequest);
+ }
+ }
+
+ public static ListPagedResponse listFilteredInstanceTemplates(String projectId,
+ String instanceTemplatePrefix) throws IOException {
+ try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {
+ ListInstanceTemplatesRequest listInstanceTemplatesRequest =
+ ListInstanceTemplatesRequest.newBuilder()
+ .setProject(projectId)
+ .setFilter(String.format("name:%s", instanceTemplatePrefix))
+ .build();
+
+ return instanceTemplatesClient.list(listInstanceTemplatesRequest);
+ }
+ }
+
+ public static String getBase64EncodedKey() {
+ String sampleSpace = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ StringBuilder stringBuilder = new StringBuilder();
+ SecureRandom random = new SecureRandom();
+ IntStream.range(0, 32)
+ .forEach(
+ x -> stringBuilder.append(sampleSpace.charAt(random.nextInt(sampleSpace.length()))));
+
+ return Base64.getEncoder()
+ .encodeToString(stringBuilder.toString().getBytes(StandardCharsets.US_ASCII));
+ }
+
+ public static String getInstanceStatus(String project, String zone, String instanceName)
+ throws IOException {
+ try (InstancesClient instancesClient = InstancesClient.create()) {
+ Instance response = instancesClient.get(project, zone, instanceName);
+ return response.getStatus();
+ }
+ }
+
}
\ No newline at end of file
diff --git a/compute/cloud-client/src/test/java/compute/customhostname/CustomHostnameInstanceIT.java b/compute/cloud-client/src/test/java/compute/customhostname/CustomHostnameInstanceIT.java
index 770b4e2aca6..4766568c834 100644
--- a/compute/cloud-client/src/test/java/compute/customhostname/CustomHostnameInstanceIT.java
+++ b/compute/cloud-client/src/test/java/compute/customhostname/CustomHostnameInstanceIT.java
@@ -25,17 +25,20 @@
import java.io.PrintStream;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
public class CustomHostnameInstanceIT {
-
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
private static String INSTANCE_NAME;
private static String ZONE;
@@ -49,8 +52,9 @@ public static void requireEnvVar(String envVarName) {
.that(System.getenv(envVarName)).isNotEmpty();
}
- @BeforeClass
- public static void setup() throws IOException, ExecutionException, InterruptedException {
+ @BeforeAll
+ public static void setup()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
@@ -70,8 +74,9 @@ public static void setup() throws IOException, ExecutionException, InterruptedEx
System.setOut(out);
}
- @AfterClass
- public static void cleanUp() throws IOException, ExecutionException, InterruptedException {
+ @AfterAll
+ public static void cleanUp()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
@@ -80,13 +85,13 @@ public static void cleanUp() throws IOException, ExecutionException, Interrupted
System.setOut(out);
}
- @Before
+ @BeforeEach
public void beforeEach() {
stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
}
- @After
+ @AfterEach
public void afterEach() {
stdOut = null;
System.setOut(null);
diff --git a/compute/cloud-client/src/test/java/compute/deleteprotection/DeleteProtectionIT.java b/compute/cloud-client/src/test/java/compute/deleteprotection/DeleteProtectionIT.java
index 7ccda634cb1..9409b1128a7 100644
--- a/compute/cloud-client/src/test/java/compute/deleteprotection/DeleteProtectionIT.java
+++ b/compute/cloud-client/src/test/java/compute/deleteprotection/DeleteProtectionIT.java
@@ -26,16 +26,20 @@
import java.io.PrintStream;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
-import org.junit.After;
-import org.junit.AfterClass;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
public class DeleteProtectionIT {
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
@@ -50,8 +54,9 @@ public static void requireEnvVar(String envVarName) {
.that(System.getenv(envVarName)).isNotEmpty();
}
- @BeforeClass
- public static void setup() throws IOException, ExecutionException, InterruptedException {
+ @BeforeAll
+ public static void setup()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
@@ -72,8 +77,9 @@ public static void setup() throws IOException, ExecutionException, InterruptedEx
System.setOut(out);
}
- @AfterClass
- public static void cleanUp() throws IOException, ExecutionException, InterruptedException {
+ @AfterAll
+ public static void cleanUp()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
@@ -88,20 +94,21 @@ public static void cleanUp() throws IOException, ExecutionException, Interrupted
System.setOut(out);
}
- @Before
+ @BeforeEach
public void beforeEach() {
stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
}
- @After
+ @AfterEach
public void afterEach() {
stdOut = null;
System.setOut(null);
}
@Test
- public void testDeleteProtection() throws IOException, ExecutionException, InterruptedException {
+ public void testDeleteProtection()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
Assert.assertTrue(GetDeleteProtection.getDeleteProtection(PROJECT_ID, ZONE, INSTANCE_NAME));
SetDeleteProtection.setDeleteProtection(PROJECT_ID, ZONE, INSTANCE_NAME, false);
Assert.assertFalse(GetDeleteProtection.getDeleteProtection(PROJECT_ID, ZONE, INSTANCE_NAME));
diff --git a/compute/cloud-client/src/test/java/compute/preemptible/PreemptibleIT.java b/compute/cloud-client/src/test/java/compute/preemptible/PreemptibleIT.java
index 5e33c314b99..98673bc14a9 100644
--- a/compute/cloud-client/src/test/java/compute/preemptible/PreemptibleIT.java
+++ b/compute/cloud-client/src/test/java/compute/preemptible/PreemptibleIT.java
@@ -28,15 +28,19 @@
import java.io.PrintStream;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
public class PreemptibleIT {
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
@@ -51,8 +55,9 @@ public static void requireEnvVar(String envVarName) {
.that(System.getenv(envVarName)).isNotEmpty();
}
- @BeforeClass
- public static void setup() throws IOException, ExecutionException, InterruptedException {
+ @BeforeAll
+ public static void setup()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
@@ -73,8 +78,9 @@ public static void setup() throws IOException, ExecutionException, InterruptedEx
System.setOut(out);
}
- @AfterClass
- public static void cleanUp() throws IOException, ExecutionException, InterruptedException {
+ @AfterAll
+ public static void cleanUp()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
final PrintStream out = System.out;
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
@@ -85,13 +91,13 @@ public static void cleanUp() throws IOException, ExecutionException, Interrupted
System.setOut(out);
}
- @Before
+ @BeforeEach
public void beforeEach() {
stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
}
- @After
+ @AfterEach
public void afterEach() {
stdOut = null;
System.setOut(null);
diff --git a/compute/cloud-client/src/test/java/compute/windows/windowsinstances/CreatingManagingWindowsInstancesIT.java b/compute/cloud-client/src/test/java/compute/windows/windowsinstances/CreatingManagingWindowsInstancesIT.java
new file mode 100644
index 00000000000..7a0d33aa094
--- /dev/null
+++ b/compute/cloud-client/src/test/java/compute/windows/windowsinstances/CreatingManagingWindowsInstancesIT.java
@@ -0,0 +1,138 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compute.windows.windowsinstances;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.cloud.compute.v1.RoutesClient;
+import compute.DeleteFirewallRule;
+import compute.DeleteInstance;
+import compute.Util;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+@Timeout(value = 10, unit = TimeUnit.MINUTES)
+public class CreatingManagingWindowsInstancesIT {
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ private static final String ZONE = "europe-central2-b";
+ private static String INSTANCE_NAME_EXTERNAL;
+ private static String INSTANCE_NAME_INTERNAL;
+ private static String FIREWALL_RULE_NAME;
+ private static String NETWORK_NAME;
+ private static String SUBNETWORK_NAME;
+ private static String ROUTE_NAME;
+
+ private ByteArrayOutputStream stdOut;
+
+ // Check if the required environment variables are set.
+ public static void requireEnvVar(String envVarName) {
+ assertWithMessage(String.format("Missing environment variable '%s' ", envVarName))
+ .that(System.getenv(envVarName)).isNotEmpty();
+ }
+
+ @BeforeAll
+ public static void setup()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ final PrintStream out = System.out;
+ ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+
+ requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
+ requireEnvVar("GOOGLE_CLOUD_PROJECT");
+
+ // Cleanup existing test instances.
+ Util.cleanUpExistingInstances("windows-test-instance", PROJECT_ID, ZONE);
+
+ String uuid = UUID.randomUUID().toString().split("-")[0];
+ INSTANCE_NAME_EXTERNAL = "windows-test-instance-external-" + uuid;
+ INSTANCE_NAME_INTERNAL = "windows-test-instance-internal-" + uuid;
+ FIREWALL_RULE_NAME = "windows-test-firewall-" + uuid;
+ NETWORK_NAME = "global/networks/default";
+ SUBNETWORK_NAME = "regions/europe-central2/subnetworks/default";
+ ROUTE_NAME = "windows-test-route-" + uuid;
+
+ stdOut.close();
+ System.setOut(out);
+ }
+
+ public static void deleteRoute()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ try (RoutesClient routesClient = RoutesClient.create()) {
+ routesClient.deleteAsync(PROJECT_ID, ROUTE_NAME).get(3, TimeUnit.MINUTES);
+ }
+ }
+
+ @BeforeEach
+ public void beforeEach() {
+ stdOut = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(stdOut));
+ }
+
+ @AfterEach
+ public void afterEach() {
+ stdOut = null;
+ System.setOut(null);
+ }
+
+ @Test
+ public void testCreateWindowsServerInstanceExternalIp()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // Create Windows server instance with external IP.
+ CreateWindowsServerInstanceExternalIp.createWindowsServerInstanceExternalIp(PROJECT_ID, ZONE,
+ INSTANCE_NAME_EXTERNAL);
+ assertThat(stdOut.toString()).contains("Instance created " + INSTANCE_NAME_EXTERNAL);
+
+ // Delete instance.
+ DeleteInstance.deleteInstance(PROJECT_ID, ZONE, INSTANCE_NAME_EXTERNAL);
+ }
+
+ @Test
+ public void testCreateWindowsServerInstanceInternalIp()
+ throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ // Create Windows server instance with internal IP and firewall rule.
+ CreateWindowsServerInstanceInternalIp.createWindowsServerInstanceInternalIp(PROJECT_ID, ZONE,
+ INSTANCE_NAME_INTERNAL, NETWORK_NAME, SUBNETWORK_NAME);
+ assertThat(stdOut.toString()).contains("Instance created " + INSTANCE_NAME_INTERNAL);
+ CreateFirewallRuleForWindowsActivationHost.createFirewallRuleForWindowsActivationHost(
+ PROJECT_ID, FIREWALL_RULE_NAME, NETWORK_NAME);
+ assertThat(stdOut.toString()).contains(
+ String.format("Firewall rule created %s", FIREWALL_RULE_NAME));
+ CreateRouteToWindowsActivationHost.createRouteToWindowsActivationHost(PROJECT_ID, ROUTE_NAME,
+ NETWORK_NAME);
+ assertThat(stdOut.toString()).contains(String.format("Route created %s", ROUTE_NAME));
+
+ // Delete Route.
+ deleteRoute();
+ // Delete Firewall.
+ DeleteFirewallRule.deleteFirewallRule(PROJECT_ID, FIREWALL_RULE_NAME);
+ // Delete Instance.
+ DeleteInstance.deleteInstance(PROJECT_ID, ZONE, INSTANCE_NAME_INTERNAL);
+ }
+}
diff --git a/compute/cmdline/pom.xml b/compute/cmdline/pom.xml
index 0991e948111..54541005105 100644
--- a/compute/cmdline/pom.xml
+++ b/compute/cmdline/pom.xml
@@ -50,7 +50,7 @@ limitations under the License.
com.google.api-client
google-api-client-gson
- 1.33.4
+ 1.34.1
diff --git a/compute/signed-metadata/pom.xml b/compute/signed-metadata/pom.xml
index 05aca3e9311..7c7d4871c48 100644
--- a/compute/signed-metadata/pom.xml
+++ b/compute/signed-metadata/pom.xml
@@ -40,7 +40,7 @@
com.auth0
java-jwt
- 3.19.1
+ 3.19.2
com.google.code.gson
diff --git a/container-registry/vulnerability-notification-function/pom.xml b/container-registry/vulnerability-notification-function/pom.xml
index 676a1d17b93..3c96669e0b7 100644
--- a/container-registry/vulnerability-notification-function/pom.xml
+++ b/container-registry/vulnerability-notification-function/pom.xml
@@ -55,7 +55,7 @@
org.projectlombok
lombok
- 1.18.22
+ 1.18.24
@@ -68,7 +68,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/dataflow/encryption-keys/pom.xml b/dataflow/encryption-keys/pom.xml
index ed19b5c70e6..00f65700009 100644
--- a/dataflow/encryption-keys/pom.xml
+++ b/dataflow/encryption-keys/pom.xml
@@ -34,7 +34,7 @@
11
UTF-8
- 2.37.0
+ 2.38.0
3.10.1
3.0.0
diff --git a/dataflow/flex-templates/kafka_to_bigquery/pom.xml b/dataflow/flex-templates/kafka_to_bigquery/pom.xml
index 2c349b37577..b2d3c9af91c 100644
--- a/dataflow/flex-templates/kafka_to_bigquery/pom.xml
+++ b/dataflow/flex-templates/kafka_to_bigquery/pom.xml
@@ -33,7 +33,7 @@
11
11
UTF-8
- 2.37.0
+ 2.38.0
7.0.2-ce
3.0.0
3.10.1
diff --git a/dataflow/flex-templates/streaming_beam_sql/pom.xml b/dataflow/flex-templates/streaming_beam_sql/pom.xml
index b877cb5565c..c4edc19608e 100644
--- a/dataflow/flex-templates/streaming_beam_sql/pom.xml
+++ b/dataflow/flex-templates/streaming_beam_sql/pom.xml
@@ -34,7 +34,7 @@
11
UTF-8
- 2.37.0
+ 2.38.0
3.0.0
3.10.1
diff --git a/dataflow/spanner-io/pom.xml b/dataflow/spanner-io/pom.xml
index c52e7f8c430..5d26ad7e5f3 100644
--- a/dataflow/spanner-io/pom.xml
+++ b/dataflow/spanner-io/pom.xml
@@ -37,7 +37,7 @@
11
11
UTF-8
- 2.37.0
+ 2.38.0
1.7.36
diff --git a/dataflow/templates/pom.xml b/dataflow/templates/pom.xml
index 6311f58d856..dce23ad332c 100644
--- a/dataflow/templates/pom.xml
+++ b/dataflow/templates/pom.xml
@@ -34,7 +34,7 @@
11
UTF-8
- 2.37.0
+ 2.38.0
3.10.1
3.0.0
diff --git a/dialogflow/basic-webhook/pom.xml b/dialogflow/basic-webhook/pom.xml
index b6c67f0e10e..b9221fc6139 100644
--- a/dialogflow/basic-webhook/pom.xml
+++ b/dialogflow/basic-webhook/pom.xml
@@ -35,7 +35,7 @@
com.google.cloud
google-cloud-dialogflow-cx
- 0.12.0
+ 0.12.1
com.google.code.gson
@@ -62,7 +62,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/endpoints/bookstore-grpc/api/build.gradle b/endpoints/bookstore-grpc/api/build.gradle
index 34811d7a609..42c2fe40874 100644
--- a/endpoints/bookstore-grpc/api/build.gradle
+++ b/endpoints/bookstore-grpc/api/build.gradle
@@ -38,12 +38,12 @@ dependencies {
protobuf {
protoc {
- artifact = 'com.google.protobuf:protoc:3.20.0'
+ artifact = 'com.google.protobuf:protoc:3.20.1'
}
plugins {
grpc {
- artifact = 'io.grpc:protoc-gen-grpc-java:1.45.1'
+ artifact = 'io.grpc:protoc-gen-grpc-java:1.46.0'
}
}
generateProtoTasks {
diff --git a/endpoints/getting-started-grpc/api/build.gradle b/endpoints/getting-started-grpc/api/build.gradle
index 1421f3a4096..68d6d057665 100644
--- a/endpoints/getting-started-grpc/api/build.gradle
+++ b/endpoints/getting-started-grpc/api/build.gradle
@@ -40,7 +40,7 @@ dependencies {
protobuf {
protoc {
- artifact = 'com.google.protobuf:protoc:3.20.0'
+ artifact = 'com.google.protobuf:protoc:3.20.1'
}
plugins {
diff --git a/endpoints/getting-started/clients/pom.xml b/endpoints/getting-started/clients/pom.xml
index c77433153fd..086c14202c7 100644
--- a/endpoints/getting-started/clients/pom.xml
+++ b/endpoints/getting-started/clients/pom.xml
@@ -33,7 +33,7 @@
com.auth0
java-jwt
- 3.19.1
+ 3.19.2
diff --git a/endpoints/getting-started/pom.xml b/endpoints/getting-started/pom.xml
index cf04bcecb25..3392f5eefef 100644
--- a/endpoints/getting-started/pom.xml
+++ b/endpoints/getting-started/pom.xml
@@ -68,7 +68,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
diff --git a/endpoints/multiple-versions/pom.xml b/endpoints/multiple-versions/pom.xml
index 898870feb3b..270fc3f20cc 100644
--- a/endpoints/multiple-versions/pom.xml
+++ b/endpoints/multiple-versions/pom.xml
@@ -38,7 +38,7 @@
2.6
- 2.4.1
+ 2.4.2
9.4.44.v20210927
false
@@ -70,6 +70,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/analytics/pom.xml b/flexible/analytics/pom.xml
index b7f1de664a4..5f057167f82 100644
--- a/flexible/analytics/pom.xml
+++ b/flexible/analytics/pom.xml
@@ -34,7 +34,7 @@
1.8
1.8
- 2.4.1
+ 2.4.2
9.4.44.v20210927
false
@@ -57,6 +57,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/async-rest/pom.xml b/flexible/async-rest/pom.xml
index 2ad87d89c1f..b4e1f5d4a9d 100644
--- a/flexible/async-rest/pom.xml
+++ b/flexible/async-rest/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
1.8
@@ -44,6 +44,11 @@
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
org.eclipse.jetty
jetty-maven-plugin
diff --git a/flexible/cloudsql/pom.xml b/flexible/cloudsql/pom.xml
index dd7ee4cbd63..07e0e744f44 100644
--- a/flexible/cloudsql/pom.xml
+++ b/flexible/cloudsql/pom.xml
@@ -56,12 +56,12 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
com.google.api-client
google-api-client-appengine
- 1.33.4
+ 1.34.0
com.google.api-client
@@ -79,7 +79,7 @@
mysql
mysql-connector-java
- 8.0.28
+ 8.0.29
com.google.cloud.sql
@@ -100,10 +100,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/flexible/cloudstorage/pom.xml b/flexible/cloudstorage/pom.xml
index 181bb8dbf8e..3c1ca6ec892 100644
--- a/flexible/cloudstorage/pom.xml
+++ b/flexible/cloudstorage/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -75,6 +75,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/cron/pom.xml b/flexible/cron/pom.xml
index ea1ab71f2ff..85ee4aca8fd 100644
--- a/flexible/cron/pom.xml
+++ b/flexible/cron/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -54,6 +54,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/datastore/pom.xml b/flexible/datastore/pom.xml
index 2434fc683ea..e4d384332d7 100644
--- a/flexible/datastore/pom.xml
+++ b/flexible/datastore/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -75,6 +75,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/disk/pom.xml b/flexible/disk/pom.xml
index a79a98c97cd..b936a875454 100644
--- a/flexible/disk/pom.xml
+++ b/flexible/disk/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -53,6 +53,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/errorreporting/pom.xml b/flexible/errorreporting/pom.xml
index 5ff163b77a2..ff487cee57c 100644
--- a/flexible/errorreporting/pom.xml
+++ b/flexible/errorreporting/pom.xml
@@ -31,7 +31,7 @@
- 2.4.1
+ 2.4.2
1.8
1.8
false
@@ -57,6 +57,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/extending-runtime/pom.xml b/flexible/extending-runtime/pom.xml
index 1af24568690..a666a3a7c98 100644
--- a/flexible/extending-runtime/pom.xml
+++ b/flexible/extending-runtime/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -53,6 +53,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/gaeinfo/pom.xml b/flexible/gaeinfo/pom.xml
index 1e5bc9dc5ff..66d401efd68 100644
--- a/flexible/gaeinfo/pom.xml
+++ b/flexible/gaeinfo/pom.xml
@@ -94,7 +94,7 @@ Copyright 2017 Google Inc.
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/flexible/helloworld-springboot/pom.xml b/flexible/helloworld-springboot/pom.xml
index 808b661df82..d5300f8d64c 100644
--- a/flexible/helloworld-springboot/pom.xml
+++ b/flexible/helloworld-springboot/pom.xml
@@ -78,7 +78,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
diff --git a/flexible/helloworld/build.gradle b/flexible/helloworld/build.gradle
index 37d52f83091..1974cdf7415 100644
--- a/flexible/helloworld/build.gradle
+++ b/flexible/helloworld/build.gradle
@@ -18,7 +18,7 @@ buildscript { // Configuration for building
mavenCentral()
}
dependencies {
- classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2'
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.3'
classpath 'org.akhikhl.gretty:gretty:+'
}
}
diff --git a/flexible/helloworld/pom.xml b/flexible/helloworld/pom.xml
index ae7b54a1dc2..0f9f039dd03 100644
--- a/flexible/helloworld/pom.xml
+++ b/flexible/helloworld/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -59,6 +59,12 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/memcache/pom.xml b/flexible/memcache/pom.xml
index 8b67bb7bd22..c53ec74a8cc 100644
--- a/flexible/memcache/pom.xml
+++ b/flexible/memcache/pom.xml
@@ -37,7 +37,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -62,6 +62,12 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/postgres/pom.xml b/flexible/postgres/pom.xml
index 33162025558..0d9f7ca3a2c 100644
--- a/flexible/postgres/pom.xml
+++ b/flexible/postgres/pom.xml
@@ -56,12 +56,12 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
com.google.api-client
google-api-client-appengine
- 1.33.4
+ 1.34.0
com.google.api-client
@@ -79,7 +79,7 @@
org.postgresql
postgresql
- 42.3.3
+ 42.3.5
@@ -102,10 +102,15 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/flexible/pubsub/pom.xml b/flexible/pubsub/pom.xml
index 8098406a014..c84f5900107 100644
--- a/flexible/pubsub/pom.xml
+++ b/flexible/pubsub/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -64,7 +64,7 @@
com.google.cloud
google-cloud-pubsub
- 1.116.3
+ 1.116.4
com.google.cloud
@@ -103,6 +103,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/sparkjava/pom.xml b/flexible/sparkjava/pom.xml
index 0cd0620f6fd..5c000f99a31 100644
--- a/flexible/sparkjava/pom.xml
+++ b/flexible/sparkjava/pom.xml
@@ -36,7 +36,7 @@ limitations under the License.
1.8
1.8
- 2.4.1
+ 2.4.2
${project.build.directory}/spark-1.0-jar-with-dependencies.jar
diff --git a/flexible/static-files/pom.xml b/flexible/static-files/pom.xml
index f96aa3e3073..bfcada7cf6a 100644
--- a/flexible/static-files/pom.xml
+++ b/flexible/static-files/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -53,6 +53,16 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/twilio/pom.xml b/flexible/twilio/pom.xml
index a94f49ee9ff..85075f89d69 100644
--- a/flexible/twilio/pom.xml
+++ b/flexible/twilio/pom.xml
@@ -36,7 +36,7 @@
false
- 2.4.1
+ 2.4.2
9.4.44.v20210927
@@ -60,6 +60,11 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
diff --git a/flexible/websocket-jetty/pom.xml b/flexible/websocket-jetty/pom.xml
index 683d8dfb51a..40c7ef68372 100644
--- a/flexible/websocket-jetty/pom.xml
+++ b/flexible/websocket-jetty/pom.xml
@@ -72,11 +72,16 @@
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/flexible/websocket-jsr356/pom.xml b/flexible/websocket-jsr356/pom.xml
index efe25e579a8..26913fbab68 100644
--- a/flexible/websocket-jsr356/pom.xml
+++ b/flexible/websocket-jsr356/pom.xml
@@ -69,11 +69,16 @@ limitations under the License.
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
GCLOUD_CONFIG
GCLOUD_CONFIG
diff --git a/functions/concepts/after-timeout/pom.xml b/functions/concepts/after-timeout/pom.xml
index fe9bcabda2e..a04d890f70f 100644
--- a/functions/concepts/after-timeout/pom.xml
+++ b/functions/concepts/after-timeout/pom.xml
@@ -61,7 +61,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/concepts/env-vars/pom.xml b/functions/concepts/env-vars/pom.xml
index ea1d4137b33..6135b52d424 100644
--- a/functions/concepts/env-vars/pom.xml
+++ b/functions/concepts/env-vars/pom.xml
@@ -55,7 +55,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/concepts/execution-count/pom.xml b/functions/concepts/execution-count/pom.xml
index dccb3e8e926..cf1ec5853b1 100644
--- a/functions/concepts/execution-count/pom.xml
+++ b/functions/concepts/execution-count/pom.xml
@@ -55,7 +55,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
@@ -68,7 +68,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/concepts/file-system/pom.xml b/functions/concepts/file-system/pom.xml
index 650fb337137..10032288559 100644
--- a/functions/concepts/file-system/pom.xml
+++ b/functions/concepts/file-system/pom.xml
@@ -55,7 +55,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/concepts/lazy-fields/pom.xml b/functions/concepts/lazy-fields/pom.xml
index c37ff0980f3..b446a676772 100644
--- a/functions/concepts/lazy-fields/pom.xml
+++ b/functions/concepts/lazy-fields/pom.xml
@@ -55,7 +55,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/concepts/retry-pubsub/pom.xml b/functions/concepts/retry-pubsub/pom.xml
index 2dded79704c..bd80719ebc7 100644
--- a/functions/concepts/retry-pubsub/pom.xml
+++ b/functions/concepts/retry-pubsub/pom.xml
@@ -69,7 +69,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/concepts/retry-timeout/pom.xml b/functions/concepts/retry-timeout/pom.xml
index c9316662539..3b71aa15f3f 100644
--- a/functions/concepts/retry-timeout/pom.xml
+++ b/functions/concepts/retry-timeout/pom.xml
@@ -68,7 +68,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/concepts/scopes/pom.xml b/functions/concepts/scopes/pom.xml
index 6d6163373d5..65068856812 100644
--- a/functions/concepts/scopes/pom.xml
+++ b/functions/concepts/scopes/pom.xml
@@ -55,7 +55,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/firebase/firestore-reactive/pom.xml b/functions/firebase/firestore-reactive/pom.xml
index 389615da5f8..50df17981d8 100644
--- a/functions/firebase/firestore-reactive/pom.xml
+++ b/functions/firebase/firestore-reactive/pom.xml
@@ -71,7 +71,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/helloworld/groovy-helloworld/pom.xml b/functions/helloworld/groovy-helloworld/pom.xml
index 763ee431026..90109716056 100644
--- a/functions/helloworld/groovy-helloworld/pom.xml
+++ b/functions/helloworld/groovy-helloworld/pom.xml
@@ -61,7 +61,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/helloworld/hello-error/src/main/java/functions/HelloError.java b/functions/helloworld/hello-error/src/main/java/functions/HelloError.java
index 9325791f24d..f12c3ce9631 100644
--- a/functions/helloworld/hello-error/src/main/java/functions/HelloError.java
+++ b/functions/helloworld/hello-error/src/main/java/functions/HelloError.java
@@ -31,11 +31,11 @@ public class HelloError implements HttpFunction {
@Override
public void service(HttpRequest request, HttpResponse response)
throws IOException {
- // These will NOT be reported to Stackdriver error reporting
+ // These will NOT be reported to Error Reporting
System.err.println("I failed you");
logger.severe("I failed you");
- // This WILL be reported to Stackdriver error reporting
+ // This WILL be reported to Error Reporting
throw new RuntimeException("I failed you");
}
}
diff --git a/functions/helloworld/hello-http-gradle/build.gradle b/functions/helloworld/hello-http-gradle/build.gradle
index 0b5f8ae154b..ccb1333c222 100644
--- a/functions/helloworld/hello-http-gradle/build.gradle
+++ b/functions/helloworld/hello-http-gradle/build.gradle
@@ -32,7 +32,7 @@ dependencies {
testImplementation 'com.google.cloud.functions:functions-framework-api:1.0.4'
testImplementation 'junit:junit:4.13.2'
testImplementation 'com.google.truth:truth:1.1.3'
- testImplementation 'org.mockito:mockito-core:4.4.0'
+ testImplementation 'org.mockito:mockito-core:4.5.1'
}
jar {
diff --git a/functions/helloworld/hello-http/pom.xml b/functions/helloworld/hello-http/pom.xml
index 0beb1ce7e0b..cbc8c0228ae 100644
--- a/functions/helloworld/hello-http/pom.xml
+++ b/functions/helloworld/hello-http/pom.xml
@@ -89,7 +89,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/helloworld/helloworld-gradle/build.gradle b/functions/helloworld/helloworld-gradle/build.gradle
index e1987d1e70d..a3741bf10a9 100644
--- a/functions/helloworld/helloworld-gradle/build.gradle
+++ b/functions/helloworld/helloworld-gradle/build.gradle
@@ -38,7 +38,7 @@ dependencies {
testImplementation 'com.google.cloud.functions:functions-framework-api:1.0.4'
testImplementation 'junit:junit:4.13.2'
testImplementation 'com.google.truth:truth:1.1.3'
- testImplementation 'org.mockito:mockito-core:4.4.0'
+ testImplementation 'org.mockito:mockito-core:4.5.1'
// [START functions_example_pom_dependencies]
// [START functions_gradle_add_dependencies]
diff --git a/functions/helloworld/helloworld/pom.xml b/functions/helloworld/helloworld/pom.xml
index 3acecf97f7a..cfefa22fa7c 100644
--- a/functions/helloworld/helloworld/pom.xml
+++ b/functions/helloworld/helloworld/pom.xml
@@ -71,7 +71,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/helloworld/kotlin-hello-pubsub/pom.xml b/functions/helloworld/kotlin-hello-pubsub/pom.xml
index c92ed4359ff..27960306fd6 100644
--- a/functions/helloworld/kotlin-hello-pubsub/pom.xml
+++ b/functions/helloworld/kotlin-hello-pubsub/pom.xml
@@ -34,7 +34,7 @@
11
11
UTF-8
- 1.6.20
+ 1.6.21
diff --git a/functions/helloworld/kotlin-helloworld/pom.xml b/functions/helloworld/kotlin-helloworld/pom.xml
index 6906a675618..8489013a09d 100644
--- a/functions/helloworld/kotlin-helloworld/pom.xml
+++ b/functions/helloworld/kotlin-helloworld/pom.xml
@@ -37,7 +37,7 @@
11
11
UTF-8
- 1.6.20
+ 1.6.21
@@ -65,7 +65,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/helloworld/scala-helloworld/pom.xml b/functions/helloworld/scala-helloworld/pom.xml
index abc76c2bc65..be052ba5bcf 100644
--- a/functions/helloworld/scala-helloworld/pom.xml
+++ b/functions/helloworld/scala-helloworld/pom.xml
@@ -59,7 +59,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/http/cors-enabled-auth/pom.xml b/functions/http/cors-enabled-auth/pom.xml
index 6165450d449..03e978b70a2 100644
--- a/functions/http/cors-enabled-auth/pom.xml
+++ b/functions/http/cors-enabled-auth/pom.xml
@@ -61,7 +61,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/http/cors-enabled/pom.xml b/functions/http/cors-enabled/pom.xml
index 1c3fb440c5d..ba979ff1843 100644
--- a/functions/http/cors-enabled/pom.xml
+++ b/functions/http/cors-enabled/pom.xml
@@ -61,7 +61,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/http/http-form-data/pom.xml b/functions/http/http-form-data/pom.xml
index 139612e1e8b..74f569067c9 100644
--- a/functions/http/http-form-data/pom.xml
+++ b/functions/http/http-form-data/pom.xml
@@ -67,7 +67,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/http/http-method/pom.xml b/functions/http/http-method/pom.xml
index baaa94f8b5e..05aeb2fa008 100644
--- a/functions/http/http-method/pom.xml
+++ b/functions/http/http-method/pom.xml
@@ -60,7 +60,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/http/parse-content-type/pom.xml b/functions/http/parse-content-type/pom.xml
index e047f5a7b8a..550c7bf9cad 100644
--- a/functions/http/parse-content-type/pom.xml
+++ b/functions/http/parse-content-type/pom.xml
@@ -66,7 +66,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/http/parse-xml/pom.xml b/functions/http/parse-xml/pom.xml
index 10b16049dbe..1dd5d139718 100644
--- a/functions/http/parse-xml/pom.xml
+++ b/functions/http/parse-xml/pom.xml
@@ -66,7 +66,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/http/send-http-request/pom.xml b/functions/http/send-http-request/pom.xml
index 4a44b13fa4b..27e57ea0c8b 100644
--- a/functions/http/send-http-request/pom.xml
+++ b/functions/http/send-http-request/pom.xml
@@ -61,7 +61,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/logging/stackdriver-logging/pom.xml b/functions/logging/stackdriver-logging/pom.xml
index 6117a9b4ab5..46e9835b679 100644
--- a/functions/logging/stackdriver-logging/pom.xml
+++ b/functions/logging/stackdriver-logging/pom.xml
@@ -105,6 +105,8 @@
3.0.0-M5
+
+ --add-opens java.base/java.time=ALL-UNNAMED
**/*Test.java
diff --git a/functions/pubsub/publish-message/pom.xml b/functions/pubsub/publish-message/pom.xml
index 85cf7a03847..3ca6c722a13 100644
--- a/functions/pubsub/publish-message/pom.xml
+++ b/functions/pubsub/publish-message/pom.xml
@@ -83,7 +83,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/slack/pom.xml b/functions/slack/pom.xml
index 065e0240812..1d36495df43 100644
--- a/functions/slack/pom.xml
+++ b/functions/slack/pom.xml
@@ -66,7 +66,7 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
@@ -77,7 +77,7 @@
com.slack.api
slack-app-backend
- 1.21.1
+ 1.22.1
@@ -90,7 +90,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/functions/spanner/pom.xml b/functions/spanner/pom.xml
index 224db35bb44..8f8049c3899 100644
--- a/functions/spanner/pom.xml
+++ b/functions/spanner/pom.xml
@@ -66,7 +66,7 @@
org.mockito
mockito-core
- 4.4.0
+ 4.5.1
test
diff --git a/healthcare/v1/pom.xml b/healthcare/v1/pom.xml
index 98dbbcde3f2..5375492d8d7 100644
--- a/healthcare/v1/pom.xml
+++ b/healthcare/v1/pom.xml
@@ -75,7 +75,7 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
com.google.apis
@@ -85,7 +85,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
com.google.auth
diff --git a/iam/api-client/pom.xml b/iam/api-client/pom.xml
index cb236ec8029..3343322171d 100644
--- a/iam/api-client/pom.xml
+++ b/iam/api-client/pom.xml
@@ -50,13 +50,13 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
com.google.apis
google-api-services-iam
- v1-rev20220331-1.32.1
+ v1-rev20220428-1.32.1
@@ -71,7 +71,7 @@
com.google.cloud
google-cloud-policy-troubleshooter
- 1.0.3
+ 1.0.4
diff --git a/iot/api-client/codelab/manager/pom.xml b/iot/api-client/codelab/manager/pom.xml
index 0f940802a5b..a481c1d34c5 100644
--- a/iot/api-client/codelab/manager/pom.xml
+++ b/iot/api-client/codelab/manager/pom.xml
@@ -67,12 +67,12 @@
com.google.apis
google-api-services-cloudiot
- v1-rev20211108-1.32.1
+ v1-rev20220425-1.32.1
com.google.cloud
google-cloud-pubsub
- 1.116.3
+ 1.116.4
com.google.cloud
@@ -87,7 +87,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
commons-cli
diff --git a/iot/api-client/end-to-end-example/pom.xml b/iot/api-client/end-to-end-example/pom.xml
index 12dfc42258e..ec2a74c338e 100644
--- a/iot/api-client/end-to-end-example/pom.xml
+++ b/iot/api-client/end-to-end-example/pom.xml
@@ -58,12 +58,12 @@
com.google.apis
google-api-services-cloudiot
- v1-rev20211108-1.32.1
+ v1-rev20220425-1.32.1
com.google.cloud
google-cloud-pubsub
- 1.116.3
+ 1.116.4
com.google.auth
@@ -78,7 +78,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
commons-cli
@@ -88,12 +88,12 @@
com.google.api-client
google-api-client-jackson2
- 1.33.4
+ 1.34.1
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
diff --git a/iot/api-client/manager/pom.xml b/iot/api-client/manager/pom.xml
index 149273c119a..cac5a6f1c72 100644
--- a/iot/api-client/manager/pom.xml
+++ b/iot/api-client/manager/pom.xml
@@ -62,12 +62,12 @@
com.google.apis
google-api-services-cloudiot
- v1-rev20211108-1.32.1
+ v1-rev20220425-1.32.1
com.google.cloud
google-cloud-pubsub
- 1.116.3
+ 1.116.4
com.google.cloud
@@ -87,7 +87,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
commons-cli
@@ -97,12 +97,12 @@
com.google.api-client
google-api-client-jackson2
- 1.33.4
+ 1.34.1
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
diff --git a/jobs/v3/pom.xml b/jobs/v3/pom.xml
index f5fb8d29bb6..94b702904db 100644
--- a/jobs/v3/pom.xml
+++ b/jobs/v3/pom.xml
@@ -42,7 +42,7 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
diff --git a/jobs/v3/src/test/java/SampleTests.java b/jobs/v3/src/test/java/SampleTests.java
index 48099d514da..287f9c8eac4 100644
--- a/jobs/v3/src/test/java/SampleTests.java
+++ b/jobs/v3/src/test/java/SampleTests.java
@@ -54,7 +54,7 @@ public void autoCompleteSampleTest() throws Exception {
assertThat(bout.toString())
.containsMatch(
".*completionResults.*\"suggestion\":"
- + "\"Google Search\",\"type\":\"COMPANY_NAME\"}.*\n"
+ + "\"Google.*\",\"type\":\"COMPANY_NAME\"}.*\n"
+ ".*completionResults.*\"suggestion\""
+ ":\"Software Engineer\",\"type\":\"JOB_TITLE\".*\n"
+ ".*completionResults.*\"suggestion\""
diff --git a/jobs/v4/pom.xml b/jobs/v4/pom.xml
index b3f80b9d0ab..a7e20928860 100644
--- a/jobs/v4/pom.xml
+++ b/jobs/v4/pom.xml
@@ -55,7 +55,7 @@
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
diff --git a/kms/pom.xml b/kms/pom.xml
index 2b90b4d7ffa..40f91c506a6 100644
--- a/kms/pom.xml
+++ b/kms/pom.xml
@@ -25,19 +25,19 @@
com.google.cloud
google-cloud-kms
- 2.4.2
+ 2.4.4
com.google.protobuf
protobuf-java-util
- 3.20.0
+ 3.20.1
com.google.protobuf
protobuf-java
- 3.20.0
+ 3.20.1
diff --git a/language/cloud-client/pom.xml b/language/cloud-client/pom.xml
index a603ff7a4c1..15411b15e89 100644
--- a/language/cloud-client/pom.xml
+++ b/language/cloud-client/pom.xml
@@ -39,7 +39,7 @@
com.google.cloud
google-cloud-language
- 2.1.10
+ 2.1.11
com.google.guava
diff --git a/media/transcoder/pom.xml b/media/transcoder/pom.xml
index 3d1e735778c..9cfdc44f36e 100644
--- a/media/transcoder/pom.xml
+++ b/media/transcoder/pom.xml
@@ -53,7 +53,7 @@
com.google.cloud
google-cloud-video-transcoder
- 1.0.3
+ 1.0.4
com.google.cloud
@@ -76,7 +76,7 @@
com.google.cloud
google-cloud-storage
- 2.6.0
+ 2.6.1
\ No newline at end of file
diff --git a/memorystore/redis/pom.xml b/memorystore/redis/pom.xml
index 3a043ceac69..1067021c90c 100644
--- a/memorystore/redis/pom.xml
+++ b/memorystore/redis/pom.xml
@@ -49,7 +49,7 @@
redis.clients
jedis
- 4.2.1
+ 4.2.3
@@ -58,6 +58,11 @@
servlet/target/visitcounter-1.0-SNAPSHOT/WEB-INF/classes
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
org.eclipse.jetty
@@ -69,7 +74,7 @@
com.google.cloud.tools
appengine-maven-plugin
- 2.4.1
+ 2.4.2
diff --git a/mlengine/online-prediction/pom.xml b/mlengine/online-prediction/pom.xml
index 9409f14e9f4..0d0e103d4e8 100644
--- a/mlengine/online-prediction/pom.xml
+++ b/mlengine/online-prediction/pom.xml
@@ -76,7 +76,7 @@ limitations under the License.
com.google.http-client
google-http-client-jackson2
- 1.41.6
+ 1.41.8
diff --git a/opencensus/pom.xml b/opencensus/pom.xml
index c73107e926b..f9140f04ee9 100644
--- a/opencensus/pom.xml
+++ b/opencensus/pom.xml
@@ -36,7 +36,7 @@
1.8
1.8
UTF-8
- 0.31.0
+ 0.31.1
diff --git a/pubsub/spring/build.gradle b/pubsub/spring/build.gradle
index f69c9f7aae3..6771f659495 100644
--- a/pubsub/spring/build.gradle
+++ b/pubsub/spring/build.gradle
@@ -34,11 +34,11 @@ description = 'Spring Cloud GCP Pub/Sub Code Sample'
java.sourceCompatibility = JavaVersion.VERSION_1_8
dependencies {
- implementation 'com.github.spotbugs:spotbugs-annotations:4.6.0'
+ implementation 'com.github.spotbugs:spotbugs-annotations:4.7.0'
implementation 'org.springframework.boot:spring-boot-starter-web:2.5.7'
- implementation 'com.google.cloud:spring-cloud-gcp-starter-pubsub:3.2.0'
- implementation 'org.springframework.integration:spring-integration-core:5.5.10'
- implementation 'com.google.cloud:spring-cloud-gcp-pubsub-stream-binder:3.2.0'
+ implementation 'com.google.cloud:spring-cloud-gcp-starter-pubsub:3.2.1'
+ implementation 'org.springframework.integration:spring-integration-core:5.5.11'
+ implementation 'com.google.cloud:spring-cloud-gcp-pubsub-stream-binder:3.2.1'
testImplementation 'junit:junit:4.13.2'
testImplementation 'com.google.truth:truth:1.1.3'
testImplementation 'org.springframework.boot:spring-boot-test:2.5.7'
diff --git a/pubsub/spring/pom.xml b/pubsub/spring/pom.xml
index 96b0160778b..4f647e074ea 100644
--- a/pubsub/spring/pom.xml
+++ b/pubsub/spring/pom.xml
@@ -55,7 +55,7 @@
com.google.cloud
spring-cloud-gcp-dependencies
- 3.2.0
+ 3.2.1
pom
import
diff --git a/pubsub/streaming-analytics/build.gradle b/pubsub/streaming-analytics/build.gradle
index 73ae05f8a8d..6da227e5235 100644
--- a/pubsub/streaming-analytics/build.gradle
+++ b/pubsub/streaming-analytics/build.gradle
@@ -33,10 +33,10 @@ repositories {
}
}
-def beamVersion = '2.37.0'
+def beamVersion = '2.38.0'
def slf4jVersion = '1.7.36'
dependencies {
- implementation 'com.github.spotbugs:spotbugs-annotations:4.6.0'
+ implementation 'com.github.spotbugs:spotbugs-annotations:4.7.0'
implementation "org.apache.beam:beam-sdks-java-core:${beamVersion}"
implementation "org.apache.beam:beam-sdks-java-io-google-cloud-platform:${beamVersion}"
implementation "org.apache.beam:beam-examples-java:${beamVersion}"
diff --git a/pubsub/streaming-analytics/pom.xml b/pubsub/streaming-analytics/pom.xml
index 854c362344e..ded6d9d9686 100644
--- a/pubsub/streaming-analytics/pom.xml
+++ b/pubsub/streaming-analytics/pom.xml
@@ -34,7 +34,7 @@
1.8
UTF-8
- 2.37.0
+ 2.38.0
3.10.1
3.0.0
diff --git a/pubsublite/streaming-analytics/build.gradle b/pubsublite/streaming-analytics/build.gradle
index 55efe9e55bd..ccf71d36cf0 100644
--- a/pubsublite/streaming-analytics/build.gradle
+++ b/pubsublite/streaming-analytics/build.gradle
@@ -33,10 +33,10 @@ repositories {
}
}
-def beamVersion = '2.37.0'
+def beamVersion = '2.38.0'
def slf4jVersion = '1.7.36'
dependencies {
- implementation 'com.github.spotbugs:spotbugs-annotations:4.6.0'
+ implementation 'com.github.spotbugs:spotbugs-annotations:4.7.0'
implementation "org.slf4j:slf4j-api:${slf4jVersion}"
implementation "org.slf4j:slf4j-jdk14:${slf4jVersion}"
implementation "org.apache.beam:beam-sdks-java-core:${beamVersion}"
@@ -44,10 +44,10 @@ dependencies {
implementation "org.apache.beam:beam-examples-java:${beamVersion}"
runtimeOnly "org.apache.beam:beam-runners-direct-java:${beamVersion}"
runtimeOnly "org.apache.beam:beam-runners-google-cloud-dataflow-java:${beamVersion}"
- testImplementation 'com.google.api-client:google-api-client:1.33.4'
+ testImplementation 'com.google.api-client:google-api-client:1.34.1'
testImplementation 'com.google.apis:google-api-services-dataflow:v1b3-rev20210825-1.32.1'
testImplementation 'com.google.cloud:google-cloud-core:2.3.2'
- testImplementation 'com.google.cloud:google-cloud-storage:2.6.0'
+ testImplementation 'com.google.cloud:google-cloud-storage:2.6.1'
testImplementation 'com.google.truth:truth:1.1.3'
testImplementation 'org.hamcrest:hamcrest-all:1.3'
}
diff --git a/pubsublite/streaming-analytics/pom.xml b/pubsublite/streaming-analytics/pom.xml
index 2423980be93..f56b2b6cb9e 100644
--- a/pubsublite/streaming-analytics/pom.xml
+++ b/pubsublite/streaming-analytics/pom.xml
@@ -34,7 +34,7 @@
11
UTF-8
- 2.37.0
+ 2.38.0
3.10.1
3.0.0
@@ -131,7 +131,7 @@
com.google.api-client
google-api-client
- 1.33.4
+ 1.34.1
diff --git a/run/endpoints-v2-backend/pom.xml b/run/endpoints-v2-backend/pom.xml
index 1513c7d953a..db48b1ce74f 100755
--- a/run/endpoints-v2-backend/pom.xml
+++ b/run/endpoints-v2-backend/pom.xml
@@ -58,7 +58,7 @@ limitations under the License.
org.springdoc
springdoc-openapi-ui
- 1.6.7
+ 1.6.8
org.springframework.boot
diff --git a/run/idp-sql/pom.xml b/run/idp-sql/pom.xml
index aff1644e257..bf350832b2e 100644
--- a/run/idp-sql/pom.xml
+++ b/run/idp-sql/pom.xml
@@ -45,7 +45,7 @@ limitations under the License.
com.google.cloud
spring-cloud-gcp-dependencies
- 3.2.0
+ 3.2.1
pom
import
@@ -80,7 +80,7 @@ limitations under the License.
net.logstash.logback
logstash-logback-encoder
- 7.0.1
+ 7.1
ch.qos.logback.contrib
@@ -106,7 +106,7 @@ limitations under the License.
org.projectlombok
lombok
- 1.18.22
+ 1.18.24
com.squareup.okhttp3
diff --git a/run/image-processing/pom.xml b/run/image-processing/pom.xml
index c7ee97c2643..75676505988 100644
--- a/run/image-processing/pom.xml
+++ b/run/image-processing/pom.xml
@@ -44,7 +44,7 @@ limitations under the License.