Skip to content

Commit

Permalink
[eventgrid] Black formatting and tests suite (#16989)
Browse files Browse the repository at this point in the history
* Black formatting

* tests

* recordings

* test
  • Loading branch information
Rakshith Bhyravabhotla authored Mar 1, 2021
1 parent 878e384 commit 92747dd
Show file tree
Hide file tree
Showing 14 changed files with 352 additions and 181 deletions.
10 changes: 7 additions & 3 deletions sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
from ._models import CloudEvent, EventGridEvent
from ._version import VERSION

__all__ = ['EventGridPublisherClient', 'CloudEvent',
'EventGridEvent', 'generate_sas', 'SystemEventNames'
]
__all__ = [
"EventGridPublisherClient",
"CloudEvent",
"EventGridEvent",
"generate_sas",
"SystemEventNames",
]
__version__ = VERSION
6 changes: 3 additions & 3 deletions sdk/eventgrid/azure-eventgrid/azure/eventgrid/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

EVENTGRID_KEY_HEADER = 'aeg-sas-key'
EVENTGRID_TOKEN_HEADER = 'aeg-sas-token'
EVENTGRID_KEY_HEADER = "aeg-sas-key"
EVENTGRID_TOKEN_HEADER = "aeg-sas-token"
DEFAULT_API_VERSION = "2018-01-01"
SAFE_ENCODE = '~()*!.\''
SAFE_ENCODE = "~()*!.'"
120 changes: 89 additions & 31 deletions sdk/eventgrid/azure-eventgrid/azure/eventgrid/_event_mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,52 @@
# --------------------------------------------------------------------------------------------
from enum import Enum


class SystemEventNames(str, Enum):
"""
This enum represents the names of the various event types for the system events published to
Azure Event Grid. To check the list of recognizable system topics,
visit https://docs.microsoft.com/azure/event-grid/system-topics.
"""
ACSChatMemberAddedToThreadWithUserEventName = "Microsoft.Communication.ChatMemberAddedToThreadWithUser"
ACSChatMemberRemovedFromThreadWithUserEventName = "Microsoft.Communication.ChatMemberRemovedFromThreadWithUser"

ACSChatMemberAddedToThreadWithUserEventName = (
"Microsoft.Communication.ChatMemberAddedToThreadWithUser"
)
ACSChatMemberRemovedFromThreadWithUserEventName = (
"Microsoft.Communication.ChatMemberRemovedFromThreadWithUser"
)
ACSChatMessageDeletedEventName = "Microsoft.Communication.ChatMessageDeleted"
ACSChatMessageEditedEventName = "Microsoft.Communication.ChatMessageEdited"
ACSChatMessageReceivedEventName = "Microsoft.Communication.ChatMessageReceived"
ACSChatThreadCreatedWithUserEventName = "Microsoft.Communication.ChatThreadCreatedWithUser"
ACSChatThreadPropertiesUpdatedPerUserEventName = "Microsoft.Communication.ChatThreadPropertiesUpdatedPerUser"
ACSChatThreadWithUserDeletedEventName = "Microsoft.Communication.ChatThreadWithUserDeleted"
ACSSMSDeliveryReportReceivedEventName = "Microsoft.Communication.SMSDeliveryReportReceived"
ACSChatThreadCreatedWithUserEventName = (
"Microsoft.Communication.ChatThreadCreatedWithUser"
)
ACSChatThreadPropertiesUpdatedPerUserEventName = (
"Microsoft.Communication.ChatThreadPropertiesUpdatedPerUser"
)
ACSChatThreadWithUserDeletedEventName = (
"Microsoft.Communication.ChatThreadWithUserDeleted"
)
ACSSMSDeliveryReportReceivedEventName = (
"Microsoft.Communication.SMSDeliveryReportReceived"
)
ACSSMSReceivedEventName = "Microsoft.Communication.SMSReceived"
AppConfigurationKeyValueDeletedEventName = "Microsoft.AppConfiguration.KeyValueDeleted"
AppConfigurationKeyValueModifiedEventName = "Microsoft.AppConfiguration.KeyValueModified"
AppConfigurationKeyValueDeletedEventName = (
"Microsoft.AppConfiguration.KeyValueDeleted"
)
AppConfigurationKeyValueModifiedEventName = (
"Microsoft.AppConfiguration.KeyValueModified"
)
ContainerRegistryChartDeletedEventName = "Microsoft.ContainerRegistry.ChartDeleted"
ContainerRegistryChartPushedEventName = "Microsoft.ContainerRegistry.ChartPushed"
ContainerRegistryImageDeletedEventName = "Microsoft.ContainerRegistry.ImageDeleted"
ContainerRegistryImagePushedEventName = "Microsoft.ContainerRegistry.ImagePushed"
EventGridSubscriptionDeletedEventName = "Microsoft.EventGrid.SubscriptionDeletedEvent"
EventGridSubscriptionValidationEventName = "Microsoft.EventGrid.SubscriptionValidationEvent"
EventGridSubscriptionDeletedEventName = (
"Microsoft.EventGrid.SubscriptionDeletedEvent"
)
EventGridSubscriptionValidationEventName = (
"Microsoft.EventGrid.SubscriptionValidationEvent"
)
EventHubCaptureFileCreatedEventName = "Microsoft.EventHub.CaptureFileCreated"
IoTHubDeviceConnectedEventName = "Microsoft.Devices.DeviceConnected"
IoTHubDeviceCreatedEventName = "Microsoft.Devices.DeviceCreated"
Expand All @@ -37,18 +59,32 @@ class SystemEventNames(str, Enum):
KeyVaultAccessPolicyChangedEventName = "Microsoft.KeyVault.VaultAccessPolicyChanged"
KeyVaultCertificateExpiredEventName = "Microsoft.KeyVault.CertificateExpired"
KeyVaultCertificateNearExpiryEventName = "Microsoft.KeyVault.CertificateNearExpiry"
KeyVaultCertificateNewVersionCreatedEventName = "Microsoft.KeyVault.CertificateNewVersionCreated"
KeyVaultCertificateNewVersionCreatedEventName = (
"Microsoft.KeyVault.CertificateNewVersionCreated"
)
KeyVaultKeyExpiredEventName = "Microsoft.KeyVault.KeyExpired"
KeyVaultKeyNearExpiryEventName = "Microsoft.KeyVault.KeyNearExpiry"
KeyVaultKeyNewVersionCreatedEventName = "Microsoft.KeyVault.KeyNewVersionCreated"
KeyVaultSecretExpiredEventName = "Microsoft.KeyVault.SecretExpired"
KeyVaultSecretNearExpiryEventName = "Microsoft.KeyVault.SecretNearExpiry"
KeyVaultSecretNewVersionCreatedEventName = "Microsoft.KeyVault.SecretNewVersionCreated"
MachineLearningServicesDatasetDriftDetectedEventName = "Microsoft.MachineLearningServices.DatasetDriftDetected"
MachineLearningServicesModelDeployedEventName = "Microsoft.MachineLearningServices.ModelDeployed"
MachineLearningServicesModelRegisteredEventName = "Microsoft.MachineLearningServices.ModelRegistered"
MachineLearningServicesRunCompletedEventName = "Microsoft.MachineLearningServices.RunCompleted"
MachineLearningServicesRunStatusChangedEventName = "Microsoft.MachineLearningServices.RunStatusChanged"
KeyVaultSecretNewVersionCreatedEventName = (
"Microsoft.KeyVault.SecretNewVersionCreated"
)
MachineLearningServicesDatasetDriftDetectedEventName = (
"Microsoft.MachineLearningServices.DatasetDriftDetected"
)
MachineLearningServicesModelDeployedEventName = (
"Microsoft.MachineLearningServices.ModelDeployed"
)
MachineLearningServicesModelRegisteredEventName = (
"Microsoft.MachineLearningServices.ModelRegistered"
)
MachineLearningServicesRunCompletedEventName = (
"Microsoft.MachineLearningServices.RunCompleted"
)
MachineLearningServicesRunStatusChangedEventName = (
"Microsoft.MachineLearningServices.RunStatusChanged"
)
MapsGeofenceEnteredEventName = "Microsoft.Maps.GeofenceEntered"
MapsGeofenceExitedEventName = "Microsoft.Maps.GeofenceExited"
MapsGeofenceResultEventName = "Microsoft.Maps.GeofenceResult"
Expand All @@ -67,15 +103,31 @@ class SystemEventNames(str, Enum):
MediaJobProcessingEventName = "Microsoft.Media.JobProcessing"
MediaJobScheduledEventName = "Microsoft.Media.JobScheduled"
MediaJobStateChangeEventName = "Microsoft.Media.JobStateChange"
MediaLiveEventConnectionRejectedEventName = "Microsoft.Media.LiveEventConnectionRejected"
MediaLiveEventEncoderConnectedEventName = "Microsoft.Media.LiveEventEncoderConnected"
MediaLiveEventEncoderDisconnectedEventName = "Microsoft.Media.LiveEventEncoderDisconnected"
MediaLiveEventIncomingDataChunkDroppedEventName = "Microsoft.Media.LiveEventIncomingDataChunkDropped"
MediaLiveEventIncomingStreamReceivedEventName = "Microsoft.Media.LiveEventIncomingStreamReceived"
MediaLiveEventIncomingStreamsOutOfSyncEventName = "Microsoft.Media.LiveEventIncomingStreamsOutOfSync"
MediaLiveEventIncomingVideoStreamsOutOfSyncEventName = "Microsoft.Media.LiveEventIncomingVideoStreamsOutOfSync"
MediaLiveEventConnectionRejectedEventName = (
"Microsoft.Media.LiveEventConnectionRejected"
)
MediaLiveEventEncoderConnectedEventName = (
"Microsoft.Media.LiveEventEncoderConnected"
)
MediaLiveEventEncoderDisconnectedEventName = (
"Microsoft.Media.LiveEventEncoderDisconnected"
)
MediaLiveEventIncomingDataChunkDroppedEventName = (
"Microsoft.Media.LiveEventIncomingDataChunkDropped"
)
MediaLiveEventIncomingStreamReceivedEventName = (
"Microsoft.Media.LiveEventIncomingStreamReceived"
)
MediaLiveEventIncomingStreamsOutOfSyncEventName = (
"Microsoft.Media.LiveEventIncomingStreamsOutOfSync"
)
MediaLiveEventIncomingVideoStreamsOutOfSyncEventName = (
"Microsoft.Media.LiveEventIncomingVideoStreamsOutOfSync"
)
MediaLiveEventIngestHeartbeatEventName = "Microsoft.Media.LiveEventIngestHeartbeat"
MediaLiveEventTrackDiscontinuityDetectedEventName = "Microsoft.Media.LiveEventTrackDiscontinuityDetected"
MediaLiveEventTrackDiscontinuityDetectedEventName = (
"Microsoft.Media.LiveEventTrackDiscontinuityDetected"
)
ResourceActionCancelEventName = "Microsoft.Resources.ResourceActionCancel"
ResourceActionFailureEventName = "Microsoft.Resources.ResourceActionFailure"
ResourceActionSuccessEventName = "Microsoft.Resources.ResourceActionSuccess"
Expand All @@ -85,17 +137,21 @@ class SystemEventNames(str, Enum):
ResourceWriteCancelEventName = "Microsoft.Resources.ResourceWriteCancel"
ResourceWriteFailureEventName = "Microsoft.Resources.ResourceWriteFailure"
ResourceWriteSuccessEventName = "Microsoft.Resources.ResourceWriteSuccess"
ServiceBusActiveMessagesAvailableWithNoListenersEventName = \
"Microsoft.ServiceBus.ActiveMessagesAvailableWithNoListeners"
ServiceBusDeadletterMessagesAvailableWithNoListenerEventName = \
"Microsoft.ServiceBus.DeadletterMessagesAvailableWithNoListener"
ServiceBusActiveMessagesAvailableWithNoListenersEventName = (
"Microsoft.ServiceBus.ActiveMessagesAvailableWithNoListeners"
)
ServiceBusDeadletterMessagesAvailableWithNoListenerEventName = (
"Microsoft.ServiceBus.DeadletterMessagesAvailableWithNoListener"
)
StorageBlobCreatedEventName = "Microsoft.Storage.BlobCreated"
StorageBlobDeletedEventName = "Microsoft.Storage.BlobDeleted"
StorageBlobRenamedEventName = "Microsoft.Storage.BlobRenamed"
StorageDirectoryCreatedEventName = "Microsoft.Storage.DirectoryCreated"
StorageDirectoryDeletedEventName = "Microsoft.Storage.DirectoryDeleted"
StorageDirectoryRenamedEventName = "Microsoft.Storage.DirectoryRenamed"
StorageLifecyclePolicyCompletedEventName = "Microsoft.Storage.LifecyclePolicyCompleted"
StorageLifecyclePolicyCompletedEventName = (
"Microsoft.Storage.LifecyclePolicyCompleted"
)
WebAppServicePlanUpdatedEventName = "Microsoft.Web.AppServicePlanUpdated"
WebAppUpdatedEventName = "Microsoft.Web.AppUpdated"
WebBackupOperationCompletedEventName = "Microsoft.Web.BackupOperationCompleted"
Expand All @@ -107,5 +163,7 @@ class SystemEventNames(str, Enum):
WebSlotSwapCompletedEventName = "Microsoft.Web.SlotSwapCompleted"
WebSlotSwapFailedEventName = "Microsoft.Web.SlotSwapFailed"
WebSlotSwapStartedEventName = "Microsoft.Web.SlotSwapStarted"
WebSlotSwapWithPreviewCancelledEventName = "Microsoft.Web.SlotSwapWithPreviewCancelled"
WebSlotSwapWithPreviewCancelledEventName = (
"Microsoft.Web.SlotSwapWithPreviewCancelled"
)
WebSlotSwapWithPreviewStartedEventName = "Microsoft.Web.SlotSwapWithPreviewStarted"
87 changes: 51 additions & 36 deletions sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import hmac
import base64
import six

try:
from urllib.parse import quote
except ImportError:
from urllib2 import quote # type: ignore
from urllib2 import quote # type: ignore

from azure.core.pipeline.policies import AzureKeyCredentialPolicy
from azure.core.credentials import AzureKeyCredential, AzureSasCredential
Expand All @@ -20,102 +21,116 @@
if TYPE_CHECKING:
from datetime import datetime


def generate_sas(endpoint, shared_access_key, expiration_date_utc, **kwargs):
# type: (str, str, datetime, Any) -> str
""" Helper method to generate shared access signature given hostname, key, and expiration date.
:param str endpoint: The topic endpoint to send the events to.
Similar to <YOUR-TOPIC-NAME>.<YOUR-REGION-NAME>-1.eventgrid.azure.net
:param str shared_access_key: The shared access key to be used for generating the token
:param datetime.datetime expiration_date_utc: The expiration datetime in UTC for the signature.
:keyword str api_version: The API Version to include in the signature.
If not provided, the default API version will be used.
:rtype: str
.. admonition:: Example:
.. literalinclude:: ../samples/sync_samples/sample_generate_sas.py
:start-after: [START generate_sas]
:end-before: [END generate_sas]
:language: python
:dedent: 0
:caption: Generate a shared access signature.
"""Helper method to generate shared access signature given hostname, key, and expiration date.
:param str endpoint: The topic endpoint to send the events to.
Similar to <YOUR-TOPIC-NAME>.<YOUR-REGION-NAME>-1.eventgrid.azure.net
:param str shared_access_key: The shared access key to be used for generating the token
:param datetime.datetime expiration_date_utc: The expiration datetime in UTC for the signature.
:keyword str api_version: The API Version to include in the signature.
If not provided, the default API version will be used.
:rtype: str
.. admonition:: Example:
.. literalinclude:: ../samples/sync_samples/sample_generate_sas.py
:start-after: [START generate_sas]
:end-before: [END generate_sas]
:language: python
:dedent: 0
:caption: Generate a shared access signature.
"""

full_endpoint = _get_full_endpoint(endpoint)

full_endpoint = "{}?apiVersion={}".format(
full_endpoint,
kwargs.get('api_version', None) or constants.DEFAULT_API_VERSION
full_endpoint, kwargs.get("api_version", None) or constants.DEFAULT_API_VERSION
)
encoded_resource = quote(full_endpoint, safe=constants.SAFE_ENCODE)
encoded_expiration_utc = quote(str(expiration_date_utc), safe=constants.SAFE_ENCODE)

unsigned_sas = "r={}&e={}".format(encoded_resource, encoded_expiration_utc)
signature = quote(_generate_hmac(shared_access_key, unsigned_sas), safe=constants.SAFE_ENCODE)
signature = quote(
_generate_hmac(shared_access_key, unsigned_sas), safe=constants.SAFE_ENCODE
)
signed_sas = "{}&s={}".format(unsigned_sas, signature)
return signed_sas


def _get_endpoint_only_fqdn(endpoint):
if endpoint.startswith('http://'):
if endpoint.startswith("http://"):
raise ValueError("HTTP is not supported. Only HTTPS is supported.")
if endpoint.startswith('https://'):
if endpoint.startswith("https://"):
endpoint = endpoint.replace("https://", "")
if endpoint.endswith("/api/events"):
endpoint = endpoint.replace("/api/events", "")

return endpoint


def _get_full_endpoint(endpoint):
if endpoint.startswith('http://'):
if endpoint.startswith("http://"):
raise ValueError("HTTP is not supported. Only HTTPS is supported.")
if not endpoint.startswith('https://'):
if not endpoint.startswith("https://"):
endpoint = "https://{}".format(endpoint)
if not endpoint.endswith("/api/events"):
endpoint = "{}/api/events".format(endpoint)

return endpoint


def _generate_hmac(key, message):
decoded_key = base64.b64decode(key)
bytes_message = message.encode('ascii')
bytes_message = message.encode("ascii")
hmac_new = hmac.new(decoded_key, bytes_message, hashlib.sha256).digest()

return base64.b64encode(hmac_new)


def _get_authentication_policy(credential):
if credential is None:
raise ValueError("Parameter 'self._credential' must not be None.")
if isinstance(credential, AzureKeyCredential):
return AzureKeyCredentialPolicy(credential=credential, name=constants.EVENTGRID_KEY_HEADER)
return AzureKeyCredentialPolicy(
credential=credential, name=constants.EVENTGRID_KEY_HEADER
)
if isinstance(credential, AzureSasCredential):
return EventGridSasCredentialPolicy(
credential=credential,
name=constants.EVENTGRID_TOKEN_HEADER
credential=credential, name=constants.EVENTGRID_TOKEN_HEADER
)
raise ValueError("The provided credential should be an instance of AzureSasCredential or AzureKeyCredential")
raise ValueError(
"The provided credential should be an instance of AzureSasCredential or AzureKeyCredential"
)


def _is_cloud_event(event):
# type: (Any) -> bool
required = ('id', 'source', 'specversion', 'type')
required = ("id", "source", "specversion", "type")
try:
return all([_ in event for _ in required]) and event['specversion'] == "1.0"
return all([_ in event for _ in required]) and event["specversion"] == "1.0"
except TypeError:
return False


def _is_eventgrid_event(event):
# type: (Any) -> bool
required = ('subject', 'eventType', 'data', 'dataVersion', 'id', 'eventTime')
required = ("subject", "eventType", "data", "dataVersion", "id", "eventTime")
try:
return all([prop in event for prop in required])
except TypeError:
return False


def _eventgrid_data_typecheck(event):
try:
data = event.get('data')
data = event.get("data")
except AttributeError:
data = event.data

if isinstance(data, six.binary_type):
raise TypeError("Data in EventGridEvent cannot be bytes. Please refer to"\
"https://docs.microsoft.com/en-us/azure/event-grid/event-schema")
raise TypeError(
"Data in EventGridEvent cannot be bytes. Please refer to"
"https://docs.microsoft.com/en-us/azure/event-grid/event-schema"
)
Loading

0 comments on commit 92747dd

Please sign in to comment.