Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 313cc87

Browse filesBrowse files
authored
feat: add eventarc generic sample and other eventarc (GoogleCloudPlatform#4845)
## Description - Adds running locally instructions like Run - Simplifies Eventarc samples. Does not use CE SDK – blocked by cloudevents/sdk-python#126 - Adds `eventarc/generic` sample Fixes GoogleCloudPlatform#4834 Ran `nox -s lint`
1 parent c4132c0 commit 313cc87
Copy full SHA for 313cc87

File tree

Expand file treeCollapse file tree

14 files changed

+427
-91
lines changed
Filter options
Expand file treeCollapse file tree

14 files changed

+427
-91
lines changed

‎eventarc/README.md

Copy file name to clipboardExpand all lines: eventarc/README.md
+28-1Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,33 @@ For more Cloud Run samples beyond Python, see the main list in the [Cloud Run Sa
3030
3131
Note: Some samples in the list above are hosted in other repositories. They are noted with the symbol "➥".
3232
33-
3433
## How to run a sample locally
3534
35+
Install [`pip`][pip] and [`virtualenv`][virtualenv] if you do not already have them.
36+
37+
You may want to refer to the [`Python Development Environment Setup Guide`][setup] for Google Cloud Platform for instructions.
38+
39+
1. Create a virtualenv. Samples are compatible with Python 2.7 and 3.4+.
40+
41+
```sh
42+
virtualenv env
43+
source env/bin/activate
44+
```
45+
46+
1. Install the dependencies needed to run the samples.
47+
48+
```sh
49+
pip install -r requirements.txt
50+
```
51+
52+
1. Start the application
53+
54+
```sh
55+
python main.py
56+
```
57+
58+
## How to run a sample in a container
59+
3660
1. [Install docker locally](https://docs.docker.com/install/)
3761
3862
2. [Build the sample container](https://cloud.google.com/run/docs/building/containers#building_locally_and_pushing_using_docker):
@@ -112,3 +136,6 @@ for more information.
112136
[events_storage]: audit-storage/README.md
113137
[anthos_events_storage]: audit-storage/anthos.md
114138
[testing]: https://cloud.google.com/run/docs/testing/local#running_locally_using_docker_with_access_to_services
139+
[setup]: https://cloud.google.com/python/setup
140+
[pip]: https://pip.pypa.io/
141+
[virtualenv]: https://virtualenv.pypa.io/

‎eventarc/audit-storage/main.py

Copy file name to clipboardExpand all lines: eventarc/audit-storage/main.py
+5-26Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,22 @@
1515
# [START eventarc_gcs_server]
1616
import os
1717

18-
import cloudevents.exceptions as cloud_exceptions
19-
from cloudevents.http import from_http
20-
2118
from flask import Flask, request
2219

2320

24-
required_fields = ['Ce-Id', 'Ce-Source', 'Ce-Type', 'Ce-Specversion']
2521
app = Flask(__name__)
2622
# [END eventarc_gcs_server]
2723

2824

2925
# [START eventarc_gcs_handler]
3026
@app.route('/', methods=['POST'])
3127
def index():
32-
# Create CloudEvent from HTTP headers and body
33-
try:
34-
event = from_http(request.headers, request.get_data())
35-
36-
except cloud_exceptions.MissingRequiredFields as e:
37-
print(f"cloudevents.exceptions.MissingRequiredFields: {e}")
38-
return "Failed to find all required cloudevent fields. ", 400
39-
40-
except cloud_exceptions.InvalidStructuredJSON as e:
41-
print(f"cloudevents.exceptions.InvalidStructuredJSON: {e}")
42-
return "Could not deserialize the payload as JSON. ", 400
43-
44-
except cloud_exceptions.InvalidRequiredFields as e:
45-
print(f"cloudevents.exceptions.InvalidRequiredFields: {e}")
46-
return "Request contained invalid required cloudevent fields. ", 400
47-
48-
if 'subject' not in event:
49-
errmsg = 'Bad Request: expected header ce-subject'
50-
print(errmsg)
51-
return errmsg, 400
28+
# Gets the GCS bucket name from the CloudEvent header
29+
# Example: "storage.googleapis.com/projects/_/buckets/my-bucket"
30+
bucket = request.headers.get('ce-subject')
5231

53-
print(f"Detected change in GCS bucket: {event['subject']}")
54-
return (f"Detected change in GCS bucket: {event['subject']}", 200)
32+
print(f"Detected change in GCS bucket: {bucket}")
33+
return (f"Detected change in GCS bucket: {bucket}", 200)
5534
# [END eventarc_gcs_handler]
5635

5736

‎eventarc/audit-storage/main_test.py

Copy file name to clipboardExpand all lines: eventarc/audit-storage/main_test.py
-20Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,3 @@ def test_endpoint(client, capsys):
4343

4444
out, _ = capsys.readouterr()
4545
assert f"Detected change in GCS bucket: {test_headers['Ce-Subject']}" in out
46-
47-
48-
def test_missing_subject(client, capsys):
49-
r = client.post('/', headers=binary_headers)
50-
assert r.status_code == 400
51-
52-
out, _ = capsys.readouterr()
53-
assert 'Bad Request: expected header ce-subject' in out
54-
55-
56-
def test_missing_required_fields(client, capsys):
57-
for field in binary_headers:
58-
test_headers = copy.copy(binary_headers)
59-
test_headers.pop(field)
60-
61-
r = client.post('/', headers=test_headers)
62-
assert r.status_code == 400
63-
64-
out, _ = capsys.readouterr()
65-
assert 'MissingRequiredFields' in out
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
Flask==1.1.2
22
gunicorn==20.0.4
3-
cloudevents==1.2.0

‎eventarc/generic/.dockerignore

Copy file name to clipboard
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Dockerfile
2+
README.md
3+
*.pyc
4+
*.pyo
5+
*.pyd
6+
__pycache__

‎eventarc/generic/Dockerfile

Copy file name to clipboard
+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2020 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_generic_dockerfile]
16+
17+
# Use the official Python image.
18+
# https://hub.docker.com/_/python
19+
FROM python:3.8-slim
20+
21+
# Allow statements and log messages to immediately appear in the Cloud Run logs
22+
ENV PYTHONUNBUFFERED True
23+
24+
# Copy application dependency manifests to the container image.
25+
# Copying this separately prevents re-running pip install on every code change.
26+
COPY requirements.txt ./
27+
28+
# Install production dependencies.
29+
RUN pip install -r requirements.txt
30+
31+
# Copy local code to the container image.
32+
ENV APP_HOME /app
33+
WORKDIR $APP_HOME
34+
COPY . ./
35+
36+
# Run the web service on container startup.
37+
# Use gunicorn webserver with one worker process and 8 threads.
38+
# For environments with multiple CPU cores, increase the number of workers
39+
# to be equal to the cores available.
40+
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
41+
# [END eventarc_generic_dockerfile]

‎eventarc/generic/main.py

Copy file name to clipboard
+50Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright 2020 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_generic_server]
16+
import os
17+
18+
from flask import Flask, request
19+
20+
21+
app = Flask(__name__)
22+
# [END eventarc_generic_server]
23+
24+
25+
# [START eventarc_generic_handler]
26+
@app.route('/', methods=['POST'])
27+
def index():
28+
print('Event received!')
29+
30+
print('HEADERS:')
31+
headers = dict(request.headers)
32+
headers.pop('Authorization', None) # do not log authorization header if exists
33+
print(headers)
34+
35+
print('BODY:')
36+
body = dict(request.json)
37+
print(body)
38+
39+
resp = {
40+
"headers": headers,
41+
"body": body
42+
}
43+
return (resp, 200)
44+
# [END eventarc_generic_handler]
45+
46+
47+
# [START eventarc_generic_server]
48+
if __name__ == "__main__":
49+
app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
50+
# [END eventarc_generic_server]

‎eventarc/generic/main_test.py

Copy file name to clipboard
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2020 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+
from uuid import uuid4
15+
16+
import pytest
17+
18+
import main
19+
20+
21+
binary_headers = {
22+
"ce-id": str(uuid4),
23+
"ce-type": "com.pytest.sample.event",
24+
"ce-source": "<my-test-source>",
25+
"ce-specversion": "1.0"
26+
}
27+
28+
29+
@pytest.fixture
30+
def client():
31+
32+
main.app.testing = True
33+
return main.app.test_client()
34+
35+
36+
def test_relay(client, capsys):
37+
38+
r = client.post('/', json={'message': {'data': 'Hello'}}, headers=binary_headers)
39+
assert r.status_code == 200
40+
41+
out, _ = capsys.readouterr()
42+
43+
# Assert print
44+
assert 'Event received!' in out
45+
46+
# Ensure output relays HTTP headers
47+
assert '"Ce-Specversion":"1.0"' in r.data.decode('utf-8')
48+
49+
# Ensure output relays HTTP body
50+
assert binary_headers['ce-id'] in out
51+
assert "{'message': {'data': 'Hello'}}" in out
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest==6.0.1

‎eventarc/generic/requirements.txt

Copy file name to clipboard
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Flask==1.1.2
2+
gunicorn==20.0.4

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.