Skip to content
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
6 changes: 3 additions & 3 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
validateMapping: true
cmd: "'functions-framework --source tests/conformance/main.py --target write_legacy_event --signature-type event'"

- name: Run cloudevent conformance tests
- name: Run CloudEvents conformance tests
uses: GoogleCloudPlatform/functions-framework-conformance/[email protected]
with:
version: 'v1.1.0'
Expand All @@ -59,11 +59,11 @@ jobs:
validateMapping: false
cmd: "'functions-framework --source tests/conformance/main.py --target write_http_declarative'"

- name: Run cloudevent conformance tests declarative
- name: Run CloudEvents conformance tests declarative
uses: GoogleCloudPlatform/functions-framework-conformance/[email protected]
with:
version: 'v1.1.0'
functionType: 'cloudevent'
useBuildpacks: false
validateMapping: true
cmd: "'functions-framework --source tests/conformance/main.py --target write_cloudevent_declarative'"
cmd: "'functions-framework --source tests/conformance/main.py --target write_cloud_event_declarative'"
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ Create an `main.py` file with the following contents:
```python
import functions_framework

@functions_framework.cloudevent
def hello_cloudevent(cloudevent):
return f"Received event with ID: {cloudevent['id']} and data {cloudevent.data}"
@functions_framework.cloud_event
def hello_cloud_event(cloud_event):
return f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}"

@functions_framework.http
def hello_http(request):
Expand All @@ -136,13 +136,13 @@ functions-framework --target=hello_http

Open http://localhost:8080/ in your browser and see *Hello world!*.

Run the following command to run `hello_cloudevent` target locally:
Run the following command to run `hello_cloud_event` target locally:

```sh
functions-framework --target=hello_cloudevent
functions-framework --target=hello_cloud_event
```

More info on sending [CloudEvents](http://cloudevents.io) payloads, see [`examples/cloud_run_cloudevents`](examples/cloud_run_cloudevents/) instruction.
More info on sending [CloudEvents](http://cloudevents.io) payloads, see [`examples/cloud_run_cloud_events`](examples/cloud_run_cloud_events/) instruction.


### Quickstart: Error handling
Expand Down Expand Up @@ -358,11 +358,11 @@ See the [running example](examples/cloud_run_event).

## Enable CloudEvents

The Functions framework can also unmarshall incoming [CloudEvents](http://cloudevents.io) payloads to the `cloudevent` object. This will be passed as a [cloudevent](https://github.com/cloudevents/sdk-python) to your function when it receives a request. Note that your function must use the `cloudevents`-style function signature:
The Functions framework can also unmarshall incoming [CloudEvents](http://cloudevents.io) payloads to the `cloud_event` object. This will be passed as a [CloudEvent](https://github.com/cloudevents/sdk-python) to your function when it receives a request. Note that your function must use the `CloudEvents`-style function signature:

```python
def hello(cloudevent):
print(f"Received event with ID: {cloudevent['id']}")
def hello(cloud_event):
print(f"Received event with ID: {cloud_event['id']}")
```

To enable automatic unmarshalling, set the function signature type to `cloudevent` using the `--signature-type` command-line flag or the `FUNCTION_SIGNATURE_TYPE` environment variable. By default, the HTTP signature type will be used and automatic event unmarshalling will be disabled.
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
### Cloud Run
* [`cloud_run_http`](./cloud_run_http/) - Deploying an HTTP function to [Cloud Run](http://cloud.google.com/run) with the Functions Framework
* [`cloud_run_event`](./cloud_run_event/) - Deploying a CloudEvent function to [Cloud Run](http://cloud.google.com/run) with the Functions Framework
* [`cloud_run_cloudevents`](./cloud_run_cloudevents/) - Deploying a [CloudEvent](https://github.com/cloudevents/sdk-python) function to [Cloud Run](http://cloud.google.com/run) with the Functions Framework
* [`cloud_run_cloud_events`](cloud_run_cloud_events/) - Deploying a [CloudEvent](https://github.com/cloudevents/sdk-python) function to [Cloud Run](http://cloud.google.com/run) with the Functions Framework

## Development Tools
* [`docker-compose`](./docker-compose) -
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ This sample uses the [CloudEvents SDK](https://github.com/cloudevents/sdk-python
Build the Docker image:

```commandline
docker build -t cloudevent_example .
docker build -t cloud_event_example .
```

Run the image and bind the correct ports:

```commandline
docker run --rm -p 8080:8080 -e PORT=8080 cloudevent_example
docker run --rm -p 8080:8080 -e PORT=8080 cloud_event_example
```

Send an event to the container:

```python
docker run -t cloudevent_example send_cloudevent.py
docker run -t cloud_event_example send_cloud_event.py
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
# (https://github.com/cloudevents/sdk-python)


def hello(cloudevent):
print(f"Received event with ID: {cloudevent['id']} and data {cloudevent.data}")
def hello(cloud_event):
print(f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}")
2 changes: 1 addition & 1 deletion examples/cloud_run_decorator/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## How to run this locally

This guide shows how to run `hello_http` target locally.
To test with `hello_cloudevent`, change the target accordingly in Dockerfile.
To test with `hello_cloud_event`, change the target accordingly in Dockerfile.

Build the Docker image:

Expand Down
6 changes: 3 additions & 3 deletions examples/cloud_run_decorator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
import functions_framework


@functions_framework.cloudevent
def hello_cloudevent(cloudevent):
return f"Received event with ID: {cloudevent['id']} and data {cloudevent.data}"
@functions_framework.cloud_event
def hello_cloud_event(cloud_event):
return f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}"


@functions_framework.http
Expand Down
14 changes: 7 additions & 7 deletions src/functions_framework/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def write(self, out):
return self.stderr.write(json.dumps(payload) + "\n")


def cloudevent(func):
def cloud_event(func):
"""Decorator that registers cloudevent as user function signature type."""
_function_registry.REGISTRY_MAP[
func.__name__
Expand Down Expand Up @@ -101,13 +101,13 @@ def view_func(path):
return view_func


def _run_cloudevent(function, request):
def _run_cloud_event(function, request):
data = request.get_data()
event = from_http(request.headers, data)
function(event)


def _cloudevent_view_func_wrapper(function, request):
def _cloud_event_view_func_wrapper(function, request):
def view_func(path):
ce_exception = None
event = None
Expand All @@ -125,7 +125,7 @@ def view_func(path):

# Not a CloudEvent. Try converting to a CloudEvent.
try:
function(event_conversion.background_event_to_cloudevent(request))
function(event_conversion.background_event_to_cloud_event(request))
except EventConversionException as e:
flask.abort(
400,
Expand All @@ -144,9 +144,9 @@ def view_func(path):

def _event_view_func_wrapper(function, request):
def view_func(path):
if event_conversion.is_convertable_cloudevent(request):
if event_conversion.is_convertable_cloud_event(request):
# Convert this CloudEvent to the equivalent background event data and context.
data, context = event_conversion.cloudevent_to_background_event(request)
data, context = event_conversion.cloud_event_to_background_event(request)
function(data, context)
elif is_binary(request.headers):
# Support CloudEvents in binary content mode, with data being the
Expand Down Expand Up @@ -214,7 +214,7 @@ def _configure_app(app, function, signature_type):
)
)

app.view_functions[signature_type] = _cloudevent_view_func_wrapper(
app.view_functions[signature_type] = _cloud_event_view_func_wrapper(
function, flask.request
)
else:
Expand Down
12 changes: 6 additions & 6 deletions src/functions_framework/event_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from functions_framework.exceptions import EventConversionException
from google.cloud.functions.context import Context

_CLOUDEVENT_SPEC_VERSION = "1.0"
_CLOUD_EVENT_SPEC_VERSION = "1.0"

# Maps background/legacy event types to their equivalent CloudEvent types.
# For more info on event mappings see
Expand Down Expand Up @@ -114,7 +114,7 @@
}


def background_event_to_cloudevent(request) -> CloudEvent:
def background_event_to_cloud_event(request) -> CloudEvent:
"""Converts a background event represented by the given HTTP request into a CloudEvent."""
event_data = marshal_background_event_data(request)
if not event_data:
Expand Down Expand Up @@ -154,7 +154,7 @@ def background_event_to_cloudevent(request) -> CloudEvent:

# Handle Firebase DB events.
if service == _FIREBASE_DB_CE_SERVICE:
# The CE source of firebasedatabase cloudevents includes location information
# The CE source of firebasedatabase CloudEvents includes location information
# that is inferred from the 'domain' field of legacy events.
if "domain" not in event_data:
raise EventConversionException(
Expand All @@ -172,7 +172,7 @@ def background_event_to_cloudevent(request) -> CloudEvent:
metadata = {
"id": context.event_id,
"time": context.timestamp,
"specversion": _CLOUDEVENT_SPEC_VERSION,
"specversion": _CLOUD_EVENT_SPEC_VERSION,
"datacontenttype": "application/json",
"type": new_type,
"source": source,
Expand All @@ -184,7 +184,7 @@ def background_event_to_cloudevent(request) -> CloudEvent:
return CloudEvent(metadata, data)


def is_convertable_cloudevent(request) -> bool:
def is_convertable_cloud_event(request) -> bool:
"""Is the given request a known CloudEvent that can be converted to background event."""
if is_binary(request.headers):
event_type = request.headers.get("ce-type")
Expand All @@ -207,7 +207,7 @@ def _split_ce_source(source) -> Tuple[str, str]:
return match.group(1), match.group(2)


def cloudevent_to_background_event(request) -> Tuple[Any, Context]:
def cloud_event_to_background_event(request) -> Tuple[Any, Context]:
"""Converts a background event represented by the given HTTP request into a CloudEvent."""
try:
event = from_http(request.headers, request.get_data())
Expand Down
10 changes: 5 additions & 5 deletions tests/conformance/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ def write_legacy_event(data, context):
)


def write_cloud_event(cloudevent):
_write_output(to_json(cloudevent).decode())
def write_cloud_event(cloud_event):
_write_output(to_json(cloud_event).decode())


@functions_framework.http
Expand All @@ -43,6 +43,6 @@ def write_http_declarative(request):
return "OK", 200


@functions_framework.cloudevent
def write_cloudevent_declarative(cloudevent):
_write_output(to_json(cloudevent).decode())
@functions_framework.cloud_event
def write_cloud_event_declarative(cloud_event):
_write_output(to_json(cloud_event).decode())
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,24 @@ def data_payload():


@pytest.fixture
def cloudevent_1_0():
def cloud_event_1_0():
attributes = {
"specversion": "1.0",
"id": "my-id",
"source": "from-galaxy-far-far-away",
"type": "cloudevent.greet.you",
"type": "cloud_event.greet.you",
"time": "2020-08-16T13:58:54.471765",
}
data = {"name": "john"}
return CloudEvent(attributes, data)


@pytest.fixture
def cloudevent_0_3():
def cloud_event_0_3():
attributes = {
"id": "my-id",
"source": "from-galaxy-far-far-away",
"type": "cloudevent.greet.you",
"type": "cloud_event.greet.you",
"specversion": "0.3",
"time": "2020-08-16T13:58:54.471765",
}
Expand All @@ -66,7 +66,7 @@ def create_headers_binary():
return lambda specversion: {
"ce-id": "my-id",
"ce-source": "from-galaxy-far-far-away",
"ce-type": "cloudevent.greet.you",
"ce-type": "cloud_event.greet.you",
"ce-specversion": specversion,
"time": "2020-08-16T13:58:54.471765",
}
Expand All @@ -77,7 +77,7 @@ def create_structured_data():
return lambda specversion: {
"id": "my-id",
"source": "from-galaxy-far-far-away",
"type": "cloudevent.greet.you",
"type": "cloud_event.greet.you",
"specversion": specversion,
"time": "2020-08-16T13:58:54.471765",
}
Expand All @@ -91,59 +91,59 @@ def background_event():

@pytest.fixture
def client():
source = TEST_FUNCTIONS_DIR / "cloudevents" / "main.py"
source = TEST_FUNCTIONS_DIR / "cloud_events" / "main.py"
target = "function"
return create_app(target, source, "cloudevent").test_client()


@pytest.fixture
def empty_client():
source = TEST_FUNCTIONS_DIR / "cloudevents" / "empty_data.py"
source = TEST_FUNCTIONS_DIR / "cloud_events" / "empty_data.py"
target = "function"
return create_app(target, source, "cloudevent").test_client()


@pytest.fixture
def converted_background_event_client():
source = TEST_FUNCTIONS_DIR / "cloudevents" / "converted_background_event.py"
source = TEST_FUNCTIONS_DIR / "cloud_events" / "converted_background_event.py"
target = "function"
return create_app(target, source, "cloudevent").test_client()


def test_event(client, cloudevent_1_0):
headers, data = to_structured(cloudevent_1_0)
def test_event(client, cloud_event_1_0):
headers, data = to_structured(cloud_event_1_0)
resp = client.post("/", headers=headers, data=data)

assert resp.status_code == 200
assert resp.data == b"OK"


def test_binary_event(client, cloudevent_1_0):
headers, data = to_binary(cloudevent_1_0)
def test_binary_event(client, cloud_event_1_0):
headers, data = to_binary(cloud_event_1_0)
resp = client.post("/", headers=headers, data=data)

assert resp.status_code == 200
assert resp.data == b"OK"


def test_event_0_3(client, cloudevent_0_3):
headers, data = to_structured(cloudevent_0_3)
def test_event_0_3(client, cloud_event_0_3):
headers, data = to_structured(cloud_event_0_3)
resp = client.post("/", headers=headers, data=data)

assert resp.status_code == 200
assert resp.data == b"OK"


def test_binary_event_0_3(client, cloudevent_0_3):
headers, data = to_binary(cloudevent_0_3)
def test_binary_event_0_3(client, cloud_event_0_3):
headers, data = to_binary(cloud_event_0_3)
resp = client.post("/", headers=headers, data=data)

assert resp.status_code == 200
assert resp.data == b"OK"


@pytest.mark.parametrize("specversion", ["0.3", "1.0"])
def test_cloudevent_missing_required_binary_fields(
def test_cloud_event_missing_required_binary_fields(
client, specversion, create_headers_binary, data_payload
):
headers = create_headers_binary(specversion)
Expand All @@ -160,7 +160,7 @@ def test_cloudevent_missing_required_binary_fields(


@pytest.mark.parametrize("specversion", ["0.3", "1.0"])
def test_cloudevent_missing_required_structured_fields(
def test_cloud_event_missing_required_structured_fields(
client, specversion, create_structured_data
):
headers = {"Content-Type": "application/cloudevents+json"}
Expand All @@ -186,7 +186,7 @@ def test_invalid_fields_binary(client, create_headers_binary, data_payload):
assert "InvalidRequiredFields" in resp.data.decode()


def test_unparsable_cloudevent(client):
def test_unparsable_cloud_event(client):
resp = client.post("/", headers={}, data="")

assert resp.status_code == 400
Expand Down
Loading