Skip to content

Commit

Permalink
feat: enable converting CloudEvent requests to Background Event reque…
Browse files Browse the repository at this point in the history
…sts (GoogleCloudPlatform#123)

This enables backwards compatability for GCF Background Functions with
newer CloudEvent-based eventing systems and brings FF Java up-to-date
with conformance tests.
  • Loading branch information
anniefu committed Oct 27, 2021
1 parent 51d6503 commit 1c4a014
Show file tree
Hide file tree
Showing 25 changed files with 812 additions and 66 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/conformance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,28 @@ jobs:
run: (cd invoker/ && mvn install)

- name: Run HTTP conformance tests
uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.0.0
uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.2.1
with:
version: 'v1.2.1'
functionType: 'http'
useBuildpacks: false
cmd: "'mvn -f invoker/conformance/pom.xml function:run -Drun.functionTarget=com.google.cloud.functions.conformance.HttpConformanceFunction'"
startDelay: 10

- name: Run background event conformance tests
uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.0.0
uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.2.1
with:
version: 'v1.2.1'
functionType: 'legacyevent'
useBuildpacks: false
validateMapping: false
validateMapping: true
cmd: "'mvn -f invoker/conformance/pom.xml function:run -Drun.functionTarget=com.google.cloud.functions.conformance.BackgroundEventConformanceFunction'"
startDelay: 10

- name: Run cloudevent conformance tests
uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.0.0
uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.2.1
with:
version: 'v1.2.1'
functionType: 'cloudevent'
useBuildpacks: false
validateMapping: true
Expand Down
10 changes: 10 additions & 0 deletions invoker/conformance/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-json-jackson</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ private String serialize(String data, Context context) {
contextJson.addProperty("timestamp", context.timestamp());
contextJson.addProperty("eventType", context.eventType());

JsonElement resource = gson.fromJson(context.resource(), JsonElement.class);
contextJson.add("resource", resource);
if (context.resource().startsWith("{")) {
JsonElement resource = gson.fromJson(context.resource(), JsonElement.class);
contextJson.add("resource", resource);
} else {
contextJson.addProperty("resource", context.resource());
}

JsonObject dataJson = gson.fromJson(data, JsonObject.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.cloud.functions.CloudEventsFunction;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.format.EventFormat;
import io.cloudevents.core.provider.EventFormatProvider;
import io.cloudevents.jackson.JsonFormat;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.time.format.DateTimeFormatter;

/**
* This class is used by the Functions Framework Conformance Tools to validate the framework's Cloud
Expand All @@ -40,33 +39,11 @@
*/
public class CloudEventsConformanceFunction implements CloudEventsFunction {

private static final Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();

@Override
public void accept(CloudEvent event) throws Exception {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("function_output.json"))) {
writer.write(serialize(event));
EventFormat format = EventFormatProvider.getInstance().resolveFormat(JsonFormat.CONTENT_TYPE);
writer.write(new String(format.serialize(event), UTF_8));
}
}

/** Create a structured JSON representation of a cloud event */
private String serialize(CloudEvent event) {
JsonObject jsonEvent = new JsonObject();

jsonEvent.addProperty("id", event.getId());
jsonEvent.addProperty("source", event.getSource().toString());
jsonEvent.addProperty("type", event.getType());
jsonEvent.addProperty("datacontenttype", event.getDataContentType());
jsonEvent.addProperty("subject", event.getSubject());
jsonEvent.addProperty("specversion", event.getSpecVersion().toString());

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
jsonEvent.addProperty("time", event.getTime().format(formatter));

String payloadJson = new String(event.getData().toBytes(), UTF_8);
JsonObject jsonObject = new Gson().fromJson(payloadJson, JsonObject.class);
jsonEvent.add("data", jsonObject);

return gson.toJson(jsonEvent);
}
}
5 changes: 5 additions & 0 deletions invoker/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.re2j</groupId>
<artifactId>re2j</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

package com.google.cloud.functions.invoker;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

Expand Down Expand Up @@ -263,10 +262,7 @@ void serviceLegacyEvent(Event legacyEvent) throws Exception {

@Override
void serviceCloudEvent(CloudEvent cloudEvent) throws Exception {
Context context = contextFromCloudEvent(cloudEvent);
String jsonData =
(cloudEvent.getData() == null) ? "{}" : new String(cloudEvent.getData().toBytes(), UTF_8);
function.accept(jsonData, context);
serviceLegacyEvent(CloudEvents.convertToLegacyEvent(cloudEvent));
}
}

Expand Down Expand Up @@ -295,10 +291,7 @@ void serviceLegacyEvent(Event legacyEvent) throws Exception {
@Override
void serviceCloudEvent(CloudEvent cloudEvent) throws Exception {
if (cloudEvent.getData() != null) {
String data = new String(cloudEvent.getData().toBytes(), UTF_8);
T payload = new Gson().fromJson(data, type);
Context context = contextFromCloudEvent(cloudEvent);
function.accept(payload, context);
serviceLegacyEvent(CloudEvents.convertToLegacyEvent(cloudEvent));
} else {
throw new IllegalStateException("Event has no \"data\" component");
}
Expand Down

0 comments on commit 1c4a014

Please sign in to comment.