diff --git a/sdk/eventgrid/azure-eventgrid/CHANGELOG.md b/sdk/eventgrid/azure-eventgrid/CHANGELOG.md index c07841352318..e51681f0958f 100644 --- a/sdk/eventgrid/azure-eventgrid/CHANGELOG.md +++ b/sdk/eventgrid/azure-eventgrid/CHANGELOG.md @@ -1,9 +1,11 @@ # Release History - -## 4.6.1 (Unreleased) + +## 4.7.0 (Unreleased) ### Features Added +- Added support for publishing native CNCF cloudevents (https://pypi.org/project/cloudevents/). + ### Breaking Changes ### Bugs Fixed diff --git a/sdk/eventgrid/azure-eventgrid/README.md b/sdk/eventgrid/azure-eventgrid/README.md index b290ce62a50d..5dc904f3df90 100644 --- a/sdk/eventgrid/azure-eventgrid/README.md +++ b/sdk/eventgrid/azure-eventgrid/README.md @@ -144,6 +144,19 @@ For complete list of recognizable system topics, visit [System Topics](https://d Event Grid on Kubernetes with Azure Arc is an offering that allows you to run Event Grid on your own Kubernetes cluster. This capability is enabled by the use of Azure Arc enabled Kubernetes. Through Azure Arc enabled Kubernetes, a supported Kubernetes cluster connects to Azure. Once connected, you are able to install Event Grid on it. Learn more about it [here](https://docs.microsoft.com/azure/event-grid/kubernetes/overview). +### Support for CNCF Cloud Events + +Starting with v4.7.0, this package also supports publishing a CNCF cloud event from https://pypi.org/project/cloudevents/. You would be able to pass a CloudEvent object from this library to the `send` API. + +```python + +from cloudevents.http import CloudEvent + +event = CloudEvent(...) + +client.send(event) +``` + ## Examples The following sections provide several code snippets covering some of the most common Event Grid tasks, including: diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py index 8c51aafffafc..f7c7bd272ad7 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py @@ -15,6 +15,7 @@ from urllib2 import quote # type: ignore from msrest import Serializer +from azure.core.exceptions import raise_with_traceback from azure.core.pipeline.transport import HttpRequest from azure.core.pipeline.policies import AzureKeyCredentialPolicy, BearerTokenCredentialPolicy from azure.core.credentials import AzureKeyCredential, AzureSasCredential @@ -98,7 +99,6 @@ def _is_cloud_event(event): except TypeError: return False - def _is_eventgrid_event(event): # type: (Any) -> bool required = ("subject", "eventType", "data", "dataVersion", "id", "eventTime") @@ -142,6 +142,22 @@ def _cloud_event_to_generated(cloud_event, **kwargs): **kwargs ) +def _from_cncf_events(event): + """This takes in a CNCF cloudevent and returns a dictionary. + If cloud events library is not installed, the event is returned back. + """ + try: + from cloudevents.http import to_json + return json.loads(to_json(event)) + except (AttributeError, ImportError): + # means this is not a CNCF event + return event + except Exception as err: # pylint: disable=broad-except + msg = """Failed to serialize the event. Please ensure your + CloudEvents is correctly formatted (https://pypi.org/project/cloudevents/)""" + raise_with_traceback(ValueError, msg, err) + + def _build_request(endpoint, content_type, events): serialize = Serializer() header_parameters = {} # type: Dict[str, Any] diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_publisher_client.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_publisher_client.py index 8878454999cc..2ae93b069535 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_publisher_client.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_publisher_client.py @@ -31,6 +31,7 @@ _eventgrid_data_typecheck, _build_request, _cloud_event_to_generated, + _from_cncf_events, ) from ._generated._event_grid_publisher_client import ( EventGridPublisherClient as EventGridPublisherClientImpl, @@ -192,7 +193,10 @@ def send(self, events, **kwargs): for e in events # pylint: disable=protected-access ] except AttributeError: - pass # means it's a dictionary + ## this is either a dictionary or a CNCF cloud event + events = [ + _from_cncf_events(e) for e in events + ] content_type = "application/cloudevents-batch+json; charset=utf-8" elif isinstance(events[0], EventGridEvent) or _is_eventgrid_event(events[0]): for event in events: diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py index 766cedfaf631..c9179def3a58 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py @@ -9,4 +9,4 @@ # regenerated. # -------------------------------------------------------------------------- -VERSION = "4.6.1" +VERSION = "4.7.0" diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_publisher_client_async.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_publisher_client_async.py index b2cb0faa33c4..59f77c03c18d 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_publisher_client_async.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_publisher_client_async.py @@ -33,6 +33,7 @@ _build_request, _cloud_event_to_generated, _get_authentication_policy, + _from_cncf_events, ) from .._generated.aio import EventGridPublisherClient as EventGridPublisherClientAsync from .._version import VERSION @@ -192,7 +193,10 @@ async def send(self, events: SendType, **kwargs: Any) -> None: for e in events # pylint: disable=protected-access ] except AttributeError: - pass # means it's a dictionary + ## this is either a dictionary or a CNCF cloud event + events = [ + _from_cncf_events(e) for e in events + ] content_type = "application/cloudevents-batch+json; charset=utf-8" elif isinstance(events[0], EventGridEvent) or _is_eventgrid_event(events[0]): for event in events: diff --git a/sdk/eventgrid/azure-eventgrid/dev_requirements.txt b/sdk/eventgrid/azure-eventgrid/dev_requirements.txt index 3f90c92310b6..8d5bbfd7a2d5 100644 --- a/sdk/eventgrid/azure-eventgrid/dev_requirements.txt +++ b/sdk/eventgrid/azure-eventgrid/dev_requirements.txt @@ -4,4 +4,5 @@ -e ../../identity/azure-identity -e ../azure-mgmt-eventgrid azure-storage-queue +cloudevents<=2.0.0; python_version >= "3.6" aiohttp>=3.0; python_version >= '3.5' diff --git a/sdk/eventgrid/azure-eventgrid/samples/async_samples/sample_publish_cncf_cloud_events_async.py b/sdk/eventgrid/azure-eventgrid/samples/async_samples/sample_publish_cncf_cloud_events_async.py new file mode 100644 index 000000000000..24b25a3c7d65 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/samples/async_samples/sample_publish_cncf_cloud_events_async.py @@ -0,0 +1,43 @@ +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- +""" +FILE: sample_publish_cncf_cloud_events_async.py +DESCRIPTION: + This sample demonstrates creating sending a cloud event from the CNCF library. +USAGE: + python sample_publish_cncf_cloud_events_async.py + Set the environment variables with your own values before running the sample: + 1) CLOUD_ACCESS_KEY - The access key of your eventgrid account. + 2) CLOUD_TOPIC_HOSTNAME - The topic hostname. Typically it exists in the format + "https://..eventgrid.azure.net/api/events". +""" +import os +import asyncio +from azure.eventgrid.aio import EventGridPublisherClient +from azure.core.credentials import AzureKeyCredential +from cloudevents.http import CloudEvent + +topic_key = os.environ["CLOUD_ACCESS_KEY"] +endpoint = os.environ["CLOUD_TOPIC_HOSTNAME"] + + +async def publish(): + + credential = AzureKeyCredential(topic_key) + client = EventGridPublisherClient(endpoint, credential) + await client.send([ + CloudEvent( + attributes={ + "type": "cloudevent", + "source": "/cncf/cloud/event/1.0", + "subject": "testingcncfevent" + }, + data=b'This is a cncf cloud event.', + ) + ]) + +if __name__ == '__main__': + asyncio.run(publish()) diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/sample_publish_cncf_cloud_events.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/sample_publish_cncf_cloud_events.py new file mode 100644 index 000000000000..bff5bee56221 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/sample_publish_cncf_cloud_events.py @@ -0,0 +1,37 @@ +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- +""" +FILE: sample_publish_cncf_cloud_events.py +DESCRIPTION: + This sample demonstrates creating sending a cloud event from the CNCF library. +USAGE: + python sample_publish_cncf_cloud_events.py + Set the environment variables with your own values before running the sample: + 1) CLOUD_ACCESS_KEY - The access key of your eventgrid account. + 2) CLOUD_TOPIC_HOSTNAME - The topic hostname. Typically it exists in the format + "https://..eventgrid.azure.net/api/events". +""" +import os +from azure.eventgrid import EventGridPublisherClient +from azure.core.credentials import AzureKeyCredential +from cloudevents.http import CloudEvent + +topic_key = os.environ["CLOUD_ACCESS_KEY"] +endpoint = os.environ["CLOUD_TOPIC_HOSTNAME"] + +credential = AzureKeyCredential(topic_key) +client = EventGridPublisherClient(endpoint, credential) + +client.send([ + CloudEvent( + attributes={ + "type": "cloudevent", + "source": "/cncf/cloud/event/1.0", + "subject": "testingcncfevent" + }, + data=b'This is a cncf cloud event.', + ) +]) diff --git a/sdk/eventgrid/azure-eventgrid/tests/conftest.py b/sdk/eventgrid/azure-eventgrid/tests/conftest.py index 2e685fe040dd..6ac5502e2b89 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/conftest.py +++ b/sdk/eventgrid/azure-eventgrid/tests/conftest.py @@ -31,3 +31,4 @@ collect_ignore_glob = [] if sys.version_info < (3, 5): collect_ignore_glob.append("*_async.py") + collect_ignore_glob.append("test_cncf*") diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_as_list.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_as_list.yaml new file mode 100644 index 000000000000..f96bbe12ff13 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_as_list.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "84b41e66-8127-4f46-850e-d62e8386e87e", "time": + "2021-10-25T03:07:58.245751+00:00", "data": "hello world"}]' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '220' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgrid/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: + - '2018-01-01' + content-length: + - '0' + date: + - Mon, 25 Oct 2021 03:07:57 GMT + server: + - Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_base64_using_data.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_base64_using_data.yaml new file mode 100644 index 000000000000..b472fd4927a4 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_base64_using_data.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "630d2dfe-6a48-455b-bd59-7c08cd070226", "time": + "2021-10-25T03:07:58.780277+00:00", "data_base64": "b''hello world''"}]' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '230' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgrid/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: + - '2018-01-01' + content-length: + - '0' + date: + - Mon, 25 Oct 2021 03:07:58 GMT + server: + - Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_dict.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_dict.yaml new file mode 100644 index 000000000000..a4a9d8fb97a9 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_dict.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "f687bede-e758-4bbd-aec9-d3f284b92238", "time": + "2021-10-25T03:07:59.100133+00:00", "data": {"message": "Hello World!"}}]' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '234' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgrid/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: + - '2018-01-01' + content-length: + - '0' + date: + - Mon, 25 Oct 2021 03:07:59 GMT + server: + - Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_none.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_none.yaml new file mode 100644 index 000000000000..dd845acb4e6e --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_none.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "0adea5e4-44e6-4c88-83f2-ab009c09ac43", "time": + "2021-10-25T03:07:59.496961+00:00", "data": null}]' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '211' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgrid/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: + - '2018-01-01' + content-length: + - '0' + date: + - Mon, 25 Oct 2021 03:07:59 GMT + server: + - Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_str.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_str.yaml new file mode 100644 index 000000000000..27c9e9babb74 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_str.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "5e41b091-7dea-4f94-a483-5d28846050b1", "time": + "2021-10-25T03:07:59.815085+00:00", "data": "hello world"}]' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '220' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgrid/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: + - '2018-01-01' + content-length: + - '0' + date: + - Mon, 25 Oct 2021 03:07:59 GMT + server: + - Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_with_extensions.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_with_extensions.yaml new file mode 100644 index 000000000000..1277587dff0a --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events.test_send_cloud_event_data_with_extensions.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "ext1": "extension", "specversion": "1.0", "id": "c55886a8-b944-4f73-acd7-a309323f07ed", + "time": "2021-10-25T03:08:00.178627+00:00", "data": "hello world"}]' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '241' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgrid/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: + - '2018-01-01' + content-length: + - '0' + date: + - Mon, 25 Oct 2021 03:07:59 GMT + server: + - Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_as_list.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_as_list.yaml new file mode 100644 index 000000000000..50e2b52dd3f2 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_as_list.yaml @@ -0,0 +1,28 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "2048d6b4-fd6e-43c1-8b21-bf5d0fac8100", "time": + "2021-10-25T03:08:54.519646+00:00", "data": "hello world"}]' + headers: + Content-Length: + - '220' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgridpublisherclient/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: '2018-01-01' + content-length: '0' + date: Mon, 25 Oct 2021 03:08:55 GMT + server: Microsoft-HTTPAPI/2.0 + strict-transport-security: max-age=31536000; includeSubDomains + status: + code: 200 + message: OK + url: https://cloudeventgridtestpwti6z.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_base64_using_data.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_base64_using_data.yaml new file mode 100644 index 000000000000..b1bf0b301b7b --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_base64_using_data.yaml @@ -0,0 +1,28 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "d9467f83-a523-4dce-a4ef-65d8d3c03e1b", "time": + "2021-10-25T03:08:55.027961+00:00", "data_base64": "b''hello world''"}]' + headers: + Content-Length: + - '230' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgridpublisherclient/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: '2018-01-01' + content-length: '0' + date: Mon, 25 Oct 2021 03:08:55 GMT + server: Microsoft-HTTPAPI/2.0 + strict-transport-security: max-age=31536000; includeSubDomains + status: + code: 200 + message: OK + url: https://cloudeventgridtestpwti6z.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_dict.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_dict.yaml new file mode 100644 index 000000000000..1203fea626e9 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_dict.yaml @@ -0,0 +1,28 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "e281a27b-9da4-4714-a9a5-837f2684fd3a", "time": + "2021-10-25T03:08:55.227972+00:00", "data": {"message": "Hello World!"}}]' + headers: + Content-Length: + - '234' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgridpublisherclient/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: '2018-01-01' + content-length: '0' + date: Mon, 25 Oct 2021 03:08:55 GMT + server: Microsoft-HTTPAPI/2.0 + strict-transport-security: max-age=31536000; includeSubDomains + status: + code: 200 + message: OK + url: https://cloudeventgridtestpwti6z.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_none.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_none.yaml new file mode 100644 index 000000000000..3923b07a8cee --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_none.yaml @@ -0,0 +1,28 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "0b0b96a4-b764-41b4-81a9-431c894e0739", "time": + "2021-10-25T03:08:55.587395+00:00", "data": null}]' + headers: + Content-Length: + - '211' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgridpublisherclient/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: '2018-01-01' + content-length: '0' + date: Mon, 25 Oct 2021 03:08:55 GMT + server: Microsoft-HTTPAPI/2.0 + strict-transport-security: max-age=31536000; includeSubDomains + status: + code: 200 + message: OK + url: https://cloudeventgridtestpwti6z.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_str.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_str.yaml new file mode 100644 index 000000000000..d2a169aa567e --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_str.yaml @@ -0,0 +1,28 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "specversion": "1.0", "id": "26d60fa4-2290-4222-8362-7ced528cc96b", "time": + "2021-10-25T03:08:55.916341+00:00", "data": "hello world"}]' + headers: + Content-Length: + - '220' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgridpublisherclient/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: '2018-01-01' + content-length: '0' + date: Mon, 25 Oct 2021 03:08:56 GMT + server: Microsoft-HTTPAPI/2.0 + strict-transport-security: max-age=31536000; includeSubDomains + status: + code: 200 + message: OK + url: https://cloudeventgridtestpwti6z.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_with_extensions.yaml b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_with_extensions.yaml new file mode 100644 index 000000000000..276b1b08010c --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/recordings/test_cncf_events_async.test_send_cloud_event_data_with_extensions.yaml @@ -0,0 +1,28 @@ +interactions: +- request: + body: '[{"type": "com.example.sampletype1", "source": "https://example.com/event-producer", + "ext1": "extension", "specversion": "1.0", "id": "5aca51d6-0b0c-478b-b479-c86bfc16ff61", + "time": "2021-10-25T03:08:56.295866+00:00", "data": "hello world"}]' + headers: + Content-Length: + - '241' + Content-Type: + - application/cloudevents-batch+json; charset=utf-8 + User-Agent: + - azsdk-python-eventgridpublisherclient/4.7.0 Python/3.7.3 (Windows-10-10.0.18362-SP0) + method: POST + uri: https://cloudeventgridtestegtopic.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 + response: + body: + string: '' + headers: + api-supported-versions: '2018-01-01' + content-length: '0' + date: Mon, 25 Oct 2021 03:08:56 GMT + server: Microsoft-HTTPAPI/2.0 + strict-transport-security: max-age=31536000; includeSubDomains + status: + code: 200 + message: OK + url: https://cloudeventgridtestpwti6z.westus-1.eventgrid.azure.net/api/events?api-version=2018-01-01 +version: 1 diff --git a/sdk/eventgrid/azure-eventgrid/tests/test_cncf_events.py b/sdk/eventgrid/azure-eventgrid/tests/test_cncf_events.py new file mode 100644 index 000000000000..c02667d4318d --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/test_cncf_events.py @@ -0,0 +1,110 @@ + +import json +from devtools_testutils import AzureTestCase, CachedResourceGroupPreparer + +from azure_devtools.scenario_tests import ReplayableTest +from azure.core.credentials import AzureKeyCredential, AzureSasCredential +from azure.eventgrid import EventGridPublisherClient +from cloudevents.http import CloudEvent + +from eventgrid_preparer import ( + CachedEventGridTopicPreparer, +) + +class EventGridPublisherClientTests(AzureTestCase): + FILTER_HEADERS = ReplayableTest.FILTER_HEADERS + ['aeg-sas-key', 'aeg-sas-token'] + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + def test_send_cloud_event_data_dict(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = {"message": "Hello World!"} + cloud_event = CloudEvent(attributes, data) + def callback(request): + req = json.loads(request.http_request.body) + assert req[0].get("data") is not None + assert isinstance(req[0], dict) + assert req[0].get("type") == "com.example.sampletype1" + assert req[0].get("source") == "https://example.com/event-producer" + + client.send(cloud_event, raw_request_hook=callback) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + def test_send_cloud_event_data_base64_using_data(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = b'hello world' + cloud_event = CloudEvent(attributes, data) + def callback(request): + req = json.loads(request.http_request.body) + assert req[0].get("data_base64") is not None + assert req[0].get("data") is None + + client.send(cloud_event, raw_request_hook=callback) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + def test_send_cloud_event_data_none(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = None + cloud_event = CloudEvent(attributes, data) + client.send(cloud_event) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + def test_send_cloud_event_data_str(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = "hello world" + def callback(request): + req = json.loads(request.http_request.body) + assert req[0].get("data_base64") is None + assert req[0].get("data") is not None + cloud_event = CloudEvent(attributes, data) + client.send(cloud_event, raw_request_hook=callback) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + def test_send_cloud_event_data_as_list(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = "hello world" + cloud_event = CloudEvent(attributes, data) + client.send([cloud_event]) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + def test_send_cloud_event_data_with_extensions(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + "ext1": "extension" + } + data = "hello world" + cloud_event = CloudEvent(attributes, data) + client.send([cloud_event]) \ No newline at end of file diff --git a/sdk/eventgrid/azure-eventgrid/tests/test_cncf_events_async.py b/sdk/eventgrid/azure-eventgrid/tests/test_cncf_events_async.py new file mode 100644 index 000000000000..156734112480 --- /dev/null +++ b/sdk/eventgrid/azure-eventgrid/tests/test_cncf_events_async.py @@ -0,0 +1,118 @@ + +import json +import pytest +from devtools_testutils import AzureTestCase, CachedResourceGroupPreparer + +from azure_devtools.scenario_tests import ReplayableTest +from azure.core.credentials import AzureKeyCredential, AzureSasCredential +from azure.eventgrid.aio import EventGridPublisherClient +from cloudevents.http import CloudEvent + +from eventgrid_preparer import ( + CachedEventGridTopicPreparer, +) + +class EventGridPublisherClientTests(AzureTestCase): + FILTER_HEADERS = ReplayableTest.FILTER_HEADERS + ['aeg-sas-key', 'aeg-sas-token'] + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + @pytest.mark.asyncio + async def test_send_cloud_event_data_dict(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = {"message": "Hello World!"} + cloud_event = CloudEvent(attributes, data) + def callback(request): + req = json.loads(request.http_request.body) + assert req[0].get("data") is not None + assert isinstance(req[0], dict) + assert req[0].get("type") == "com.example.sampletype1" + assert req[0].get("source") == "https://example.com/event-producer" + + await client.send(cloud_event, raw_request_hook=callback) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + @pytest.mark.asyncio + async def test_send_cloud_event_data_base64_using_data(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = b'hello world' + cloud_event = CloudEvent(attributes, data) + def callback(request): + req = json.loads(request.http_request.body) + assert req[0].get("data_base64") is not None + assert req[0].get("data") is None + + await client.send(cloud_event, raw_request_hook=callback) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + @pytest.mark.asyncio + async def test_send_cloud_event_data_none(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = None + cloud_event = CloudEvent(attributes, data) + await client.send(cloud_event) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + @pytest.mark.asyncio + async def test_send_cloud_event_data_str(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = "hello world" + cloud_event = CloudEvent(attributes, data) + def callback(request): + req = json.loads(request.http_request.body) + assert req[0].get("data_base64") is None + assert req[0].get("data") is not None + + await client.send(cloud_event, raw_request_hook=callback) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + @pytest.mark.asyncio + async def test_send_cloud_event_data_as_list(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + } + data = "hello world" + cloud_event = CloudEvent(attributes, data) + await client.send([cloud_event]) + + @CachedResourceGroupPreparer(name_prefix='eventgridtest') + @CachedEventGridTopicPreparer(name_prefix='cloudeventgridtest') + @pytest.mark.asyncio + async def test_send_cloud_event_data_with_extensions(self, resource_group, eventgrid_topic, eventgrid_topic_primary_key, eventgrid_topic_endpoint): + akc_credential = AzureKeyCredential(eventgrid_topic_primary_key) + client = EventGridPublisherClient(eventgrid_topic_endpoint, akc_credential) + attributes = { + "type": "com.example.sampletype1", + "source": "https://example.com/event-producer", + "ext1": "extension" + } + data = "hello world" + cloud_event = CloudEvent(attributes, data) + await client.send([cloud_event]) diff --git a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client.py b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client.py index 3651363c2435..735d58ba74e7 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client.py +++ b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client.py @@ -19,7 +19,7 @@ except ImportError: from urlparse import urlparse -from devtools_testutils import AzureMgmtTestCase, CachedResourceGroupPreparer +from devtools_testutils import AzureTestCase, CachedResourceGroupPreparer from azure_devtools.scenario_tests import ReplayableTest from azure.core.credentials import AzureKeyCredential, AzureSasCredential @@ -32,7 +32,7 @@ CachedEventGridTopicPreparer, ) -class EventGridPublisherClientTests(AzureMgmtTestCase): +class EventGridPublisherClientTests(AzureTestCase): FILTER_HEADERS = ReplayableTest.FILTER_HEADERS + ['aeg-sas-key', 'aeg-sas-token'] @CachedResourceGroupPreparer(name_prefix='eventgridtest') diff --git a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py index b2ec715a6a65..0483fd9328b7 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py +++ b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py @@ -15,7 +15,7 @@ from urllib.parse import urlparse import datetime as dt -from devtools_testutils import AzureMgmtTestCase, CachedResourceGroupPreparer +from devtools_testutils import AzureTestCase, CachedResourceGroupPreparer from azure_devtools.scenario_tests import ReplayableTest from azure.core.credentials import AzureKeyCredential, AzureSasCredential @@ -30,7 +30,7 @@ ) -class EventGridPublisherClientTests(AzureMgmtTestCase): +class EventGridPublisherClientTests(AzureTestCase): FILTER_HEADERS = ReplayableTest.FILTER_HEADERS + ['aeg-sas-key', 'aeg-sas-token'] @CachedResourceGroupPreparer(name_prefix='eventgridtest')