Skip to content

Commit 4687063

Browse files
muncuskweinmeistergcf-owl-bot[bot]
authored
feat(eventarc): new sample for storage event receiver (GoogleCloudPlatform#10222)
* feat(eventarc): cloudevent GCS handler * Procfile, for easier cloud run deployment * lint cleanups * lint errors from headers and imports * flake8 import order fix * fix region tags * really fix the region tag * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * improve error handling, tests, per @grayside. --------- Co-authored-by: Karl Weinmeister <11586922+kweinmeister@users.noreply.github.com> Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 4718999 commit 4687063

5 files changed

Lines changed: 121 additions & 0 deletions

File tree

eventarc/storage_handler/Procfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

eventarc/storage_handler/main.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright 2023 Google LLC.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START eventarc_storage_cloudevent_server]
16+
import os
17+
18+
from cloudevents.http import from_http
19+
20+
from flask import Flask, request
21+
22+
from google.events.cloud.storage import StorageObjectData
23+
24+
25+
app = Flask(__name__)
26+
# [END eventarc_storage_cloudevent_server]
27+
28+
29+
# [START eventarc_storage_cloudevent_handler]
30+
@app.route("/", methods=["POST"])
31+
def index():
32+
event = from_http(request.headers, request.get_data())
33+
34+
# Gets the GCS bucket name from the CloudEvent data
35+
# Example: "storage.googleapis.com/projects/_/buckets/my-bucket"
36+
try:
37+
storage_obj = StorageObjectData(event.data)
38+
gcs_object = os.path.join(storage_obj.bucket, storage_obj.name)
39+
update_time = storage_obj.updated
40+
return (
41+
f"Cloud Storage object changed: {gcs_object}"
42+
+ f" updated at {update_time}",
43+
200,
44+
)
45+
except ValueError as e:
46+
return (f"Failed to parse event data: {e}", 400)
47+
48+
49+
# [END eventarc_storage_cloudevent_handler]
50+
51+
52+
# [START eventarc_storage_cloudevent_server]
53+
if __name__ == "__main__":
54+
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
55+
# [END eventarc_storage_cloudevent_server]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Copyright 2023 Google LLC.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START eventarc_testing_cloudevent]
16+
from uuid import uuid4
17+
18+
from cloudevents.conversion import to_binary
19+
from cloudevents.http import CloudEvent
20+
21+
from google.events.cloud.storage import StorageObjectData
22+
23+
import pytest
24+
25+
import main
26+
27+
28+
ce_attributes = {
29+
"id": str(uuid4),
30+
"type": "com.pytest.sample.event",
31+
"source": "<my-test-source>",
32+
"specversion": "1.0",
33+
}
34+
35+
36+
@pytest.fixture
37+
def client():
38+
main.app.testing = True
39+
return main.app.test_client()
40+
41+
42+
def test_endpoint(client):
43+
storagedata = StorageObjectData(bucket="test-bucket", name="my-file.txt")
44+
event = CloudEvent(ce_attributes, StorageObjectData.to_dict(storagedata))
45+
headers, body = to_binary(event)
46+
47+
r = client.post("/", headers=headers, data=body)
48+
assert r.status_code == 200
49+
assert "Cloud Storage object changed: test-bucket/my-file.txt" in r.text
50+
51+
52+
# [END eventarc_testing_cloudevent]
53+
54+
55+
def test_invalid_data(client):
56+
event = CloudEvent(ce_attributes, {"an_unknown_field": "some_value"})
57+
headers, body = to_binary(event)
58+
59+
r = client.post("/", headers=headers, data=body)
60+
assert r.status_code == 400
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest==7.0.1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Flask==2.1.0
2+
gunicorn==20.1.0
3+
google-events==0.7.0
4+
cloudevents==1.9.0

0 commit comments

Comments
 (0)