Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Google Cloud Functions http bindings #9645

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ci-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,13 @@ jobs:
java :
- { name: Java8,
java-version: 8,
maven_args: "-pl !integration-tests/vault-app,!integration-tests/vault-agroal,!integration-tests/vault"
maven_args: "-pl !integration-tests/vault-app,!integration-tests/vault-agroal,!integration-tests/vault,!integration-tests/google-cloud-functions-http"
patriot1burke marked this conversation as resolved.
Show resolved Hide resolved
}
- {
name: "Java 8 - 242",
java-version: 8,
release: "jdk8u242-b08"
release: "jdk8u242-b08",
maven_args: "-pl !integration-tests/google-cloud-functions-http"
}
- {
name: Java 11,
Expand Down
6 changes: 6 additions & 0 deletions bom/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,12 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-google-cloud-functions-http-deployment</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Quarkus extension dependencies -->
<dependency>
<groupId>org.webjars</groupId>
Expand Down
11 changes: 11 additions & 0 deletions bom/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@

<picocli.version>4.3.2</picocli.version>
<org.eclipse.sisu.inject.version>0.3.4</org.eclipse.sisu.inject.version>
<google-cloud-functions.version>1.0.1</google-cloud-functions.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -1040,6 +1041,11 @@
<artifactId>quarkus-cache</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-google-cloud-functions-http</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Quarkus test dependencies -->
<dependency>
Expand Down Expand Up @@ -1193,6 +1199,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.cloud.functions</groupId>
<artifactId>functions-framework-api</artifactId>
<version>${google-cloud-functions.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
Expand Down
214 changes: 214 additions & 0 deletions docs/src/main/asciidoc/gcp-functions-http.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Google Cloud Functions (Serverless) with RESTEasy, Undertow, or Vert.x Web
:extension-status: preview

include::./attributes.adoc[]

The `quarkus-google-cloud-functions-http` extension allows you to write microservices with RESTEasy (JAX-RS),
Undertow (servlet) or Vert.x Web, and make these microservices deployable to the Google Cloud Functions runtime.

One Google Cloud Functions deployment can represent any number of JAX-RS, servlet, or Vert.x Web endpoints.

include::./status-include.adoc[]

== Prerequisites

To complete this guide, you need:

* less than 15 minutes
* JDK 11 (Google Cloud Functions requires JDK 11)
* Apache Maven {maven-version}
* https://cloud.google.com/[A Google Cloud Account]. Free accounts work.
* https://cloud.google.com/sdk[Cloud SDK CLI Installed]

== Solution

This guide walks you through running a Maven Archetype to generate a sample project then creating three http endpoints
written with JAX-RS APIs, Servlet APIs or Vert.x Web APIs. After building, you will then be able to deploy
to Google Cloud.

== Creating the Maven Deployment Project

Create an application with the `quarkus-google-cloud-functions-http` extension.
You can use the following Maven command to create it:

[source,shell,subs=attributes+]
----
mvn io.quarkus:quarkus-maven-plugin:{quarkus-version}:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=google-cloud-functions-http \
-DclassName="org.acme.quickstart.GreetingResource" \
-Dpath="/hello" \
-Dextensions="google-cloud-functions-http,resteasy-json,undertow,vertx-web"
----

== Login to Google Cloud

If you don't login to Google Cloud you won't be able to deploy.

[source, subs=attributes+]
----
gcloud auth login
----

At the time writing this guide, Cloud Functions are still in beta so make sure to install the `beta` command group.

[source, subs=attributes+]
----
gcloud components install beta
----

== Creating the endpoints

For this example project, we will create three endpoints, one for RESTEasy (JAX-RS), one for Undertow (Servlet)
and one for Vert.x Web (reactive routes).

If you don't want endpoints to all these technologies, you can remove the unnecessary extensions from your `pom.xml`.

=== The JAX-RS endpoint

[source,java]
----
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
----

=== The Servlet endpoint

[source,java]
----
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "ServletGreeting", urlPatterns = "/servlet/hello")
public class GreetingServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setStatus(200);
resp.addHeader("Content-Type", "text/plain");
resp.getWriter().write("hello");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getReader().readLine();
resp.setStatus(200);
resp.addHeader("Content-Type", "text/plain");
resp.getWriter().write("hello " + name);
}
}
----

=== The Vert.x Web endpoint

[source,java]
----
import static io.vertx.core.http.HttpMethod.GET;

import io.quarkus.vertx.web.Route;
import io.vertx.ext.web.RoutingContext;

public class GreetingRoutes {
@Route(path = "/vertx/hello", methods = GET)
void hello(RoutingContext context) {
context.response().headers().set("Content-Type", "text/plain");
context.response().setStatusCode(200).end("hello");
}
}
----

== Build and Deploy to Google Cloud

To build your application, you first need to define a packaging of type `uber-jar` via your `application.properties`.

[source]
----
quarkus.package.uber-jar=true
----

Then you can package your application via `mvn clean package`.
You will have a single JAR inside the target repository that contains your classes and all your dependencies in it.

To deploy your JAR to Google Cloud, you need to pass a directory with only this JAR inside it, to the `gcloud` utility.

So first, create a `deployment` directory and copy the generated artifact inside it.

[source]
----
mkdir deployment
cp target/google-cloud-functions-http-1.0-SNAPSHOT-runner.jar deployment/
----

Then you will be able to use `gcloud` to deploy your function to Google Cloud.

[source]
----
gcloud beta functions deploy quarkus-example-http \
--entry-point=io.quarkus.gcp.functions.http.QuarkusHttpFunction \
--runtime=java11 --trigger-http --source=deployment
----

[WARNING]
----
The first time you launch this command, you can have the following error message:
```
ERROR: (gcloud.beta.functions.deploy) OperationError: code=7, message=Build Failed: Cloud Build has not been used in project <project_name> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudbuild.googleapis.com/overview?project=<my-project> then retry.
```
This means that Cloud Build is not activated yet, please go to the mentionned URL to activate it, wait a few minutes and retry the command.
----

The entry point always needs to be `io.quarkus.gcp.functions.http.QuarkusHttpFunction` as it will be this class
that bootstraps Quarkus.

This command will give you as output a `httpsTrigger.url` that point to your function.

You can then call your endpoints via:

- For JAX-RS: {httpsTrigger.url}/hello
- For servlet: {httpsTrigger.url}/servlet/hello
- For Vert.x Web: {httpsTrigger.url}/vertx/hello

== Testing locally

The easiest way to locally test your function is using the Cloud Function invoker JAR.

You can download it via Maven using the following command:

[source]
----
mvn dependency:copy \
-Dartifact='com.google.cloud.functions.invoker:java-function-invoker:1.0.0-beta1' \
-DoutputDirectory=.
----

Then you can use it to launch your function locally.

[source]
----
java -jar java-function-invoker-1.0.0-beta1.jar \
--classpath target/google-cloud-functions-http-1.0-SNAPSHOT-runner.jar \
--target io.quarkus.gcp.functions.http.QuarkusHttpFunction
----

Your endpoints will be available on http://localhost:8080.
47 changes: 47 additions & 0 deletions extensions/google-cloud-functions-http/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<parent>
<artifactId>quarkus-google-cloud-functions-http-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-google-cloud-functions-http-deployment</artifactId>
<name>Quarkus - HTTP Google Cloud Functions - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-http-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.gcp.functions.http.deployment;

import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.vertx.http.deployment.RequireVirtualHttpBuildItem;

public class GoogleCloudFunctionsHttpProcessor {
private static final String FEATURE_NAME = "google-cloud-functions-http";

@BuildStep
public FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE_NAME);
}

@BuildStep
public RunTimeConfigurationDefaultBuildItem disableBanner() {
// the banner is not displayed well inside the Google Cloud Function logs
return new RunTimeConfigurationDefaultBuildItem("quarkus.banner.enabled", "false");
}

@BuildStep
public RequireVirtualHttpBuildItem requestVirtualHttp(LaunchModeBuildItem launchMode) {
return launchMode.getLaunchMode() == LaunchMode.NORMAL ? RequireVirtualHttpBuildItem.MARKER : null;
}
}
22 changes: 22 additions & 0 deletions extensions/google-cloud-functions-http/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<parent>
<artifactId>quarkus-build-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../../build-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-google-cloud-functions-http-parent</artifactId>
<name>Quarkus - HTTP Google Cloud Functions</name>
<packaging>pom</packaging>

<modules>
<module>runtime</module>
<module>deployment</module>
</modules>

</project>
Loading