Reputation: 299
So I am switching from cloud functions to Cloud Run and I am trying to figure out how to run Event Arc locally. I know you can set up an emulator for Eventarc using Firebase Emulator but Im not sure to have it trigger one of my Cloud Run functions when I write to my local Firestore db. Can someone please let me know how this can be done?
I did see one vague answer here:
Emulation of event-driven design in Cloud Run while developing locally?
But to me this doesn't make sense given that if Im using the local DB and local functions how would a remote instance work with my local dev environment. If this is possible please let me know and how I can accomplish this. Thanks.
Upvotes: 4
Views: 1219
Reputation: 84
Just for completeness on guillaume blaquiere's answer, this is the code I used:
Create a python cloud run function with an EventArc trigger of type Storage -> google.cloud.storage.object.v1.finalized in production with this code:
import functions_framework
from cloudevents.http import CloudEvent
@functions_framework.cloud_event
def hello_gcs(cloud_event: CloudEvent) -> None:
for item in cloud_event:
print(f"Item: {item} -> {cloud_event[item]}")
data = cloud_event.data
for my_data_item in data:
print(f"Data Item: {my_data_item} -> {data[my_data_item]}")
Then upload a file in the Storage Bucket, which should trigger the cloud run function.
From the Google Cloud Log Explorer, you can extract the values received by the Cloud Function.
With these values, you can construct either a curl request or in my case I rather use a python script like this:
import requests
import json
url = "http://localhost:5001" # Local cloud run function
headers = {
"Content-Type": "application/cloudevents+json"
}
data = {
"specversion": "1.0",
"type": "google.cloud.storage.object.v1.finalized",
"source": "//storage.googleapis.com/projects/_/buckets/my-bucket-test",
"subject": "objects/my_file.jpg",
"id": "12102065114832012",
"time": "2024-08-30T20:10:00Z",
"data": {
"kind": "storage#object",
"id": "my-bucket-test/1725048606538342",
"selfLink": "https://www.googleapis.com/storage/v1/b/my-bucket-test/o/",
"name": "my_file.jpg",
"bucket": "my-bucket-test",
"generation": "1725048606538342",
"metageneration": "1",
"contentType": "image/jpeg",
"timeCreated": "2024-08-30T20:10:06.542Z",
"updated": "2024-08-30T20:10:06.542Z",
"storageClass": "STANDARD",
"timeStorageClassUpdated": "2024-08-30T20:10:06.542Z",
"size": "0",
"md5Hash": "1B2ABC8AsgTpgAmY7PhCfg==",
"mediaLink": "https://storage.googleapis.com/download/storage/v1/b/my-bucket-test/o/generation=1725048606538342&alt=media",
"crc32c": "AAAAAA==",
"etag": "COb0puvCnYgDEAE=",
"temporaryHold": False,
"eventBasedHold": False
}
}
response = requests.post(url, headers=headers, data=json.dumps(data))
print(response.status_code)
print(response.text)
And then have a local cloud run function @ localhost:5001 like this:
import functions_framework
from cloudevents.http import CloudEvent
@functions_framework.cloud_event
def hello_gcs(cloud_event: CloudEvent) -> None:
for item in cloud_event:
print(f"Item: {item} -> {cloud_event[item]}")
data = cloud_event.data
for my_data_item in data:
print(f"Data Item: {my_data_item} -> {data[my_data_item]}")
I tried using the Firebase Eventarc emulator, but it fails if the Firebase Cloud Functions emulator is not running. In my case, I'm not using the Firebase Cloud Functions, but the Google Cloud Run functions.
Upvotes: 0
Reputation: 75765
It's not an easy task and the team is working to make the local tests easier. For now, I can share my hack.
First of all, you have to know that eventarc is roughtly a wrapper that create several resources behind the scene, especially a PubSub topic and Push subscription to your Cloud Run service. Because of that, an eventarc event is no more than a POST request with the event content as body.
For my hack, I have a Cloud Run service, on GCP, that log the headers and body of any incoming requests. I set up an eventarc with that service as target, and I trigger an event.
I go to the logs, copy the headers and the body of the received event, and I create a curl POST request with that.
Then, when I want to test my local service, I reuse my curl POST request, and submit it to my localhost server.
Upvotes: 1