diff --git a/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py b/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py new file mode 100644 index 00000000000..7af5992a20d --- /dev/null +++ b/aws_lambda_powertools/utilities/parser/models/iot_registry_events.py @@ -0,0 +1,129 @@ +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +from pydantic import BaseModel, Field + +EVENT_CRUD_OPERATION = Literal["CREATED", "UPDATED", "DELETED"] +EVENT_ADD_REMOVE_OPERATION = Literal["ADDED", "REMOVED"] + + +class IoTCoreRegistryEventsBase(BaseModel): + event_id: str = Field(..., alias="eventId") + timestamp: datetime + + +class IoTCoreThingEvent(IoTCoreRegistryEventsBase): + """ + Thing Created/Updated/Deleted + + The registry publishes event messages when things are created, updated, or deleted. + """ + + event_type: Literal["THING_EVENT"] = Field(..., alias="eventType") + operation: EVENT_CRUD_OPERATION + thing_id: str = Field(..., alias="thingId") + account_id: str = Field(..., alias="accountId") + thing_name: str = Field(..., alias="thingName") + version_number: int = Field(..., alias="versionNumber") + thing_type_name: Optional[str] = Field(None, alias="thingTypeName") + attributes: Dict[str, Any] + + +class IoTCoreThingTypeEvent(IoTCoreRegistryEventsBase): + """ + Thing Type Created/Updated/Deprecated/Undeprecated/Deleted + The registry publishes event messages when thing types are created, updated, deprecated, undeprecated, or deleted. + + Format: + $aws/events/thingType/thingTypeName/created + $aws/events/thingType/thingTypeName/updated + $aws/events/thingType/thingTypeName/deleted + """ + + event_type: Literal["THING_TYPE_EVENT"] = Field(..., alias="eventType") + operation: EVENT_CRUD_OPERATION + account_id: str = Field(..., alias="accountId") + thing_type_id: str = Field(..., alias="thingTypeId") + thing_type_name: str = Field(..., alias="thingTypeName") + is_deprecated: bool = Field(..., alias="isDeprecated") + deprecation_date: Optional[datetime] = Field(None, alias="deprecationDate") + searchable_attributes: List[str] = Field(..., alias="searchableAttributes") + propagating_attributes: List[Dict[str, str]] = Field(..., alias="propagatingAttributes") + description: str + + +class IoTCoreThingTypeAssociationEvent(IoTCoreRegistryEventsBase): + """ + The registry publishes event messages when a thing type is associated or disassociated with a thing. + + Format: + $aws/events/thingTypeAssociation/thing/thingName/thingType/typeName/added + $aws/events/thingTypeAssociation/thing/thingName/thingType/typeName/removed + """ + + event_type: Literal["THING_TYPE_ASSOCIATION_EVENT"] = Field(..., alias="eventType") + operation: EVENT_ADD_REMOVE_OPERATION + thing_id: str = Field(..., alias="thingId") + thing_name: str = Field(..., alias="thingName") + thing_type_name: str = Field(..., alias="thingTypeName") + + +class IoTCoreThingGroupEvent(IoTCoreRegistryEventsBase): + """ + The registry publishes the following event messages when a thing group is created, updated, or deleted. + + Format: + $aws/events/thingGroup/groupName/created + $aws/events/thingGroup/groupName/updated + $aws/events/thingGroup/groupName/deleted + """ + + event_type: Literal["THING_GROUP_EVENT"] = Field(..., alias="eventType") + operation: EVENT_CRUD_OPERATION + account_id: str = Field(..., alias="accountId") + thing_group_id: str = Field(..., alias="thingGroupId") + thing_group_name: str = Field(..., alias="thingGroupName") + version_number: int = Field(..., alias="versionNumber") + parent_group_name: Optional[str] = Field(None, alias="parentGroupName") + parent_group_id: Optional[str] = Field(None, alias="parentGroupId") + description: str + root_to_parent_thing_groups: List[Dict[str, str]] = Field(..., alias="rootToParentThingGroups") + attributes: Dict[str, Any] + dynamic_group_mapping_id: Optional[str] = Field(None, alias="dynamicGroupMappingId") + + +class IoTCoreAddOrRemoveFromThingGroupEvent(IoTCoreRegistryEventsBase): + """ + The registry publishes event messages when a thing is added to or removed from a thing group. + + Format: + $aws/events/thingGroupMembership/thingGroup/thingGroupName/thing/thingName/added + $aws/events/thingGroupMembership/thingGroup/thingGroupName/thing/thingName/removed + """ + + event_type: Literal["THING_GROUP_MEMBERSHIP_EVENT"] = Field(..., alias="eventType") + operation: EVENT_ADD_REMOVE_OPERATION + account_id: str = Field(..., alias="accountId") + group_arn: str = Field(..., alias="groupArn") + group_id: str = Field(..., alias="groupId") + thing_arn: str = Field(..., alias="thingArn") + thing_id: str = Field(..., alias="thingId") + membership_id: str = Field(..., alias="membershipId") + + +class IoTCoreAddOrDeleteFromThingGroupEvent(IoTCoreRegistryEventsBase): + """ + The registry publishes event messages when a thing group is added to or removed from another thing group. + + Format: + $aws/events/thingGroupHierarchy/thingGroup/parentThingGroupName/childThingGroup/childThingGroupName/added + $aws/events/thingGroupHierarchy/thingGroup/parentThingGroupName/childThingGroup/childThingGroupName/removed + """ + + event_type: Literal["THING_GROUP_HIERARCHY_EVENT"] = Field(..., alias="eventType") + operation: EVENT_ADD_REMOVE_OPERATION + account_id: str = Field(..., alias="accountId") + thing_group_id: str = Field(..., alias="thingGroupId") + thing_group_name: str = Field(..., alias="thingGroupName") + child_group_id: str = Field(..., alias="childGroupId") + child_group_name: str = Field(..., alias="childGroupName") diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 1df9c2342f1..b6abbe965e1 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -100,41 +100,47 @@ You can use pre-built models to work events from AWS services, so you don’t ne The example above uses `SqsModel`. Other built-in models can be found below. -| Model name | Description | -| ------------------------------------------- | ------------------------------------------------------------------------------------- | -| **AlbModel** | Lambda Event Source payload for Amazon Application Load Balancer | -| **APIGatewayProxyEventModel** | Lambda Event Source payload for Amazon API Gateway | -| **ApiGatewayAuthorizerToken** | Lambda Event Source payload for Amazon API Gateway Lambda Authorizer with Token | -| **ApiGatewayAuthorizerRequest** | Lambda Event Source payload for Amazon API Gateway Lambda Authorizer with Request | -| **APIGatewayProxyEventV2Model** | Lambda Event Source payload for Amazon API Gateway v2 payload | -| **ApiGatewayAuthorizerRequestV2** | Lambda Event Source payload for Amazon API Gateway v2 Lambda Authorizer | -| **APIGatewayWebSocketMessageEventModel** | Lambda Event Source payload for Amazon API Gateway WebSocket API message body | -| **APIGatewayWebSocketConnectEventModel** | Lambda Event Source payload for Amazon API Gateway WebSocket API $connect message | -| **APIGatewayWebSocketDisconnectEventModel** | Lambda Event Source payload for Amazon API Gateway WebSocket API $disconnect message | -| **BedrockAgentEventModel** | Lambda Event Source payload for Bedrock Agents | -| **CloudFormationCustomResourceCreateModel** | Lambda Event Source payload for AWS CloudFormation `CREATE` operation | -| **CloudFormationCustomResourceUpdateModel** | Lambda Event Source payload for AWS CloudFormation `UPDATE` operation | -| **CloudFormationCustomResourceDeleteModel** | Lambda Event Source payload for AWS CloudFormation `DELETE` operation | -| **CloudwatchLogsModel** | Lambda Event Source payload for Amazon CloudWatch Logs | -| **DynamoDBStreamModel** | Lambda Event Source payload for Amazon DynamoDB Streams | -| **EventBridgeModel** | Lambda Event Source payload for Amazon EventBridge | -| **KafkaMskEventModel** | Lambda Event Source payload for AWS MSK payload | -| **KafkaSelfManagedEventModel** | Lambda Event Source payload for self managed Kafka payload | -| **KinesisDataStreamModel** | Lambda Event Source payload for Amazon Kinesis Data Streams | -| **KinesisFirehoseModel** | Lambda Event Source payload for Amazon Kinesis Firehose | -| **KinesisFirehoseSqsModel** | Lambda Event Source payload for SQS messages wrapped in Kinesis Firehose records | -| **LambdaFunctionUrlModel** | Lambda Event Source payload for Lambda Function URL payload | -| **S3BatchOperationModel** | Lambda Event Source payload for Amazon S3 Batch Operation | -| **S3EventNotificationEventBridgeModel** | Lambda Event Source payload for Amazon S3 Event Notification to EventBridge. | -| **S3Model** | Lambda Event Source payload for Amazon S3 | -| **S3ObjectLambdaEvent** | Lambda Event Source payload for Amazon S3 Object Lambda | -| **S3SqsEventNotificationModel** | Lambda Event Source payload for S3 event notifications wrapped in SQS event (S3->SQS) | -| **SesModel** | Lambda Event Source payload for Amazon Simple Email Service | -| **SnsModel** | Lambda Event Source payload for Amazon Simple Notification Service | -| **SqsModel** | Lambda Event Source payload for Amazon SQS | -| **TransferFamilyAuthorizer** | Lambda Event Source payload for AWS Transfer Family Lambda authorizer | -| **VpcLatticeModel** | Lambda Event Source payload for Amazon VPC Lattice | -| **VpcLatticeV2Model** | Lambda Event Source payload for Amazon VPC Lattice v2 payload | +| Model name | Description | +| ------------------------------------------- | --------------------------------------------------------------------------------------------- | +| **AlbModel** | Lambda Event Source payload for Amazon Application Load Balancer | +| **APIGatewayProxyEventModel** | Lambda Event Source payload for Amazon API Gateway | +| **ApiGatewayAuthorizerToken** | Lambda Event Source payload for Amazon API Gateway Lambda Authorizer with Token | +| **ApiGatewayAuthorizerRequest** | Lambda Event Source payload for Amazon API Gateway Lambda Authorizer with Request | +| **APIGatewayProxyEventV2Model** | Lambda Event Source payload for Amazon API Gateway v2 payload | +| **ApiGatewayAuthorizerRequestV2** | Lambda Event Source payload for Amazon API Gateway v2 Lambda Authorizer | +| **APIGatewayWebSocketMessageEventModel** | Lambda Event Source payload for Amazon API Gateway WebSocket API message body | +| **APIGatewayWebSocketConnectEventModel** | Lambda Event Source payload for Amazon API Gateway WebSocket API $connect message | +| **APIGatewayWebSocketDisconnectEventModel** | Lambda Event Source payload for Amazon API Gateway WebSocket API $disconnect message | +| **BedrockAgentEventModel** | Lambda Event Source payload for Bedrock Agents | +| **CloudFormationCustomResourceCreateModel** | Lambda Event Source payload for AWS CloudFormation `CREATE` operation | +| **CloudFormationCustomResourceUpdateModel** | Lambda Event Source payload for AWS CloudFormation `UPDATE` operation | +| **CloudFormationCustomResourceDeleteModel** | Lambda Event Source payload for AWS CloudFormation `DELETE` operation | +| **CloudwatchLogsModel** | Lambda Event Source payload for Amazon CloudWatch Logs | +| **DynamoDBStreamModel** | Lambda Event Source payload for Amazon DynamoDB Streams | +| **EventBridgeModel** | Lambda Event Source payload for Amazon EventBridge | +| **IoTCoreThingEvent** | Lambda Event Source payload for IoT Core Thing created, updated, or deleted. | +| **IoTCoreThingTypeEvent** | Lambda Event Source payload for IoT Core Thing Type events. | +| **IoTCoreThingTypeAssociationEvent** | Lambda Event Source payload for IoT Core Thing Type associated or disassociated with a Thing. | +| **IoTCoreThingGroupEvent** | Lambda Event Source payload for IoT Core Thing Group created, updated, or deleted. | +| **IoTCoreAddOrRemoveFromThingGroupEvent** | Lambda Event Source payload for IoT Core Thing added to or removed from a Thing Group. | +| **IoTCoreAddOrDeleteFromThingGroupEvent** | Lambda Event Source payload for IoT Core Thing Group added to or deleted from a Thing Group. | +| **KafkaMskEventModel** | Lambda Event Source payload for AWS MSK payload | +| **KafkaSelfManagedEventModel** | Lambda Event Source payload for self managed Kafka payload | +| **KinesisDataStreamModel** | Lambda Event Source payload for Amazon Kinesis Data Streams | +| **KinesisFirehoseModel** | Lambda Event Source payload for Amazon Kinesis Firehose | +| **KinesisFirehoseSqsModel** | Lambda Event Source payload for SQS messages wrapped in Kinesis Firehose records | +| **LambdaFunctionUrlModel** | Lambda Event Source payload for Lambda Function URL payload | +| **S3BatchOperationModel** | Lambda Event Source payload for Amazon S3 Batch Operation | +| **S3EventNotificationEventBridgeModel** | Lambda Event Source payload for Amazon S3 Event Notification to EventBridge. | +| **S3Model** | Lambda Event Source payload for Amazon S3 | +| **S3ObjectLambdaEvent** | Lambda Event Source payload for Amazon S3 Object Lambda | +| **S3SqsEventNotificationModel** | Lambda Event Source payload for S3 event notifications wrapped in SQS event (S3->SQS) | +| **SesModel** | Lambda Event Source payload for Amazon Simple Email Service | +| **SnsModel** | Lambda Event Source payload for Amazon Simple Notification Service | +| **SqsModel** | Lambda Event Source payload for Amazon SQS | +| **TransferFamilyAuthorizer** | Lambda Event Source payload for AWS Transfer Family Lambda authorizer | +| **VpcLatticeModel** | Lambda Event Source payload for Amazon VPC Lattice | +| **VpcLatticeV2Model** | Lambda Event Source payload for Amazon VPC Lattice v2 payload | #### Extending built-in models diff --git a/tests/events/codePipelineEventWithEncryptionKey.json b/tests/events/codePipelineEventWithEncryptionKey.json index e4a8528e148..46b75536c41 100644 --- a/tests/events/codePipelineEventWithEncryptionKey.json +++ b/tests/events/codePipelineEventWithEncryptionKey.json @@ -30,7 +30,7 @@ }, "continuationToken": "A continuation token if continuing job", "encryptionKey": { - "id": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", + "id": "validkmskey", "type": "KMS" } } diff --git a/tests/events/iotRegistryEventsAddOrDeleteFromThingGroupEvent.json b/tests/events/iotRegistryEventsAddOrDeleteFromThingGroupEvent.json new file mode 100644 index 00000000000..6bb09236e46 --- /dev/null +++ b/tests/events/iotRegistryEventsAddOrDeleteFromThingGroupEvent.json @@ -0,0 +1,11 @@ +{ + "eventType": "THING_GROUP_HIERARCHY_EVENT", + "eventId": "264192c7-b573-46ef-ab7b-489fcd47da41", + "timestamp": 1234567890123, + "operation": "ADDED", + "accountId": "123456789012", + "thingGroupId": "8f82a106-6b1d-4331-8984-a84db5f6f8cb", + "thingGroupName": "MyRootThingGroup", + "childGroupId": "06838589-373f-4312-b1f2-53f2192291c4", + "childGroupName": "MyChildThingGroup" +} diff --git a/tests/events/iotRegistryEventsAddOrRemoveFromThingGroupEvent.json b/tests/events/iotRegistryEventsAddOrRemoveFromThingGroupEvent.json new file mode 100644 index 00000000000..35c1fa0ae04 --- /dev/null +++ b/tests/events/iotRegistryEventsAddOrRemoveFromThingGroupEvent.json @@ -0,0 +1,12 @@ +{ + "eventType": "THING_GROUP_MEMBERSHIP_EVENT", + "eventId": "d684bd5f-6f6e-48e1-950c-766ac7f02fd1", + "timestamp": 1234567890123, + "operation": "ADDED", + "accountId": "123456789012", + "groupArn": "arn:aws:iot:ap-northeast-2:123456789012:thinggroup/MyChildThingGroup", + "groupId": "06838589-373f-4312-b1f2-53f2192291c4", + "thingArn": "arn:aws:iot:ap-northeast-2:123456789012:thing/MyThing", + "thingId": "b604f69c-aa9a-4d4a-829e-c480e958a0b5", + "membershipId": "8505ebf8-4d32-4286-80e9-c23a4a16bbd8" +} diff --git a/tests/events/iotRegistryEventsThingEvent.json b/tests/events/iotRegistryEventsThingEvent.json new file mode 100644 index 00000000000..08db220337d --- /dev/null +++ b/tests/events/iotRegistryEventsThingEvent.json @@ -0,0 +1,12 @@ +{ + "eventType": "THING_EVENT", + "eventId": "f5ae9b94-8b8e-4d8e-8c8f-b3266dd89853", + "timestamp": 1234567890123, + "operation": "CREATED", + "accountId": "123456789012", + "thingId": "b604f69c-aa9a-4d4a-829e-c480e958a0b5", + "thingName": "MyThing", + "versionNumber": 1, + "thingTypeName": null, + "attributes": {"attribute3": "value3", "attribute1": "value1", "attribute2": "value2"} +} diff --git a/tests/events/iotRegistryEventsThingGroupEvent.json b/tests/events/iotRegistryEventsThingGroupEvent.json new file mode 100644 index 00000000000..3a68f5f15db --- /dev/null +++ b/tests/events/iotRegistryEventsThingGroupEvent.json @@ -0,0 +1,37 @@ +{ + "eventType": "THING_GROUP_EVENT", + "eventId": "8b9ea8626aeaa1e42100f3f32b975899", + "timestamp": 1603995417409, + "operation": "UPDATED", + "accountId": "571EXAMPLE833", + "thingGroupId": "8757eec8-bb37-4cca-a6fa-403b003d139f", + "thingGroupName": "Tg_level5", + "versionNumber": 3, + "parentGroupName": "Tg_level4", + "parentGroupId": "5fce366a-7875-4c0e-870b-79d8d1dce119", + "description": "New description for Tg_level5", + "rootToParentThingGroups": [ + { + "groupArn": "arn:aws:iot:us-west-2:571EXAMPLE833:thinggroup/TgTopLevel", + "groupId": "36aa0482-f80d-4e13-9bff-1c0a75c055f6" + }, + { + "groupArn": "arn:aws:iot:us-west-2:571EXAMPLE833:thinggroup/Tg_level1", + "groupId": "bc1643e1-5a85-4eac-b45a-92509cbe2a77" + }, + { + "groupArn": "arn:aws:iot:us-west-2:571EXAMPLE833:thinggroup/Tg_level2", + "groupId": "0476f3d2-9beb-48bb-ae2c-ea8bd6458158" + }, + { + "groupArn": "arn:aws:iot:us-west-2:571EXAMPLE833:thinggroup/Tg_level3", + "groupId": "1d9d4ffe-a6b0-48d6-9de6-2e54d1eae78f" + }, + { + "groupArn": "arn:aws:iot:us-west-2:571EXAMPLE833:thinggroup/Tg_level4", + "groupId": "5fce366a-7875-4c0e-870b-79d8d1dce119" + } + ], + "attributes": {"attribute1": "value1", "attribute3": "value3", "attribute2": "value2"}, + "dynamicGroupMappingId": null +} diff --git a/tests/events/iotRegistryEventsThingTypeAssociationEvent.json b/tests/events/iotRegistryEventsThingTypeAssociationEvent.json new file mode 100644 index 00000000000..23d8cdea5bd --- /dev/null +++ b/tests/events/iotRegistryEventsThingTypeAssociationEvent.json @@ -0,0 +1,9 @@ +{ + "eventId": "87f8e095-531c-47b3-aab5-5171364d138d", + "eventType": "THING_TYPE_ASSOCIATION_EVENT", + "operation": "ADDED", + "thingId": "b604f69c-aa9a-4d4a-829e-c480e958a0b5", + "thingName": "myThing", + "thingTypeName": "MyThingType", + "timestamp": 1234567890123 +} diff --git a/tests/events/iotRegistryEventsThingTypeEvent.json b/tests/events/iotRegistryEventsThingTypeEvent.json new file mode 100644 index 00000000000..c205d86d015 --- /dev/null +++ b/tests/events/iotRegistryEventsThingTypeEvent.json @@ -0,0 +1,17 @@ +{ + "eventType": "THING_TYPE_EVENT", + "eventId": "8827376c-4b05-49a3-9b3b-733729df7ed5", + "timestamp": 1234567890123, + "operation": "CREATED", + "accountId": "123456789012", + "thingTypeId": "c530ae83-32aa-4592-94d3-da29879d1aac", + "thingTypeName": "MyThingType", + "isDeprecated": false, + "deprecationDate": null, + "searchableAttributes": ["attribute1", "attribute2", "attribute3"], + "propagatingAttributes": [ + {"userPropertyKey": "key", "thingAttribute": "model"}, + {"userPropertyKey": "key", "connectionAttribute": "iot:ClientId"} + ], + "description": "My thing type" +} diff --git a/tests/functional/parameters/_boto3/test_utilities_parameters.py b/tests/functional/parameters/_boto3/test_utilities_parameters.py index fc4d869472e..42f654cbd1e 100644 --- a/tests/functional/parameters/_boto3/test_utilities_parameters.py +++ b/tests/functional/parameters/_boto3/test_utilities_parameters.py @@ -617,7 +617,7 @@ def test_ssm_provider_set_parameter_with_custom_options(monkeypatch, mock_name, "Overwrite": True, "Tier": "Advanced", "Description": "Parameter", - "KeyId": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", + "KeyId": "validkmskey", } stubber.add_response("put_parameter", response, expected_params) stubber.activate() @@ -631,7 +631,7 @@ def test_ssm_provider_set_parameter_with_custom_options(monkeypatch, mock_name, parameter_type="SecureString", overwrite=True, description="Parameter", - kms_key_id="arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", + kms_key_id="validkmskey", ) assert version == response diff --git a/tests/unit/parser/_pydantic/test_iot_registry_events.py b/tests/unit/parser/_pydantic/test_iot_registry_events.py new file mode 100644 index 00000000000..a36e44e2a52 --- /dev/null +++ b/tests/unit/parser/_pydantic/test_iot_registry_events.py @@ -0,0 +1,115 @@ +from aws_lambda_powertools.utilities.parser.models.iot_registry_events import ( + IoTCoreAddOrDeleteFromThingGroupEvent, + IoTCoreAddOrRemoveFromThingGroupEvent, + IoTCoreThingEvent, + IoTCoreThingGroupEvent, + IoTCoreThingTypeAssociationEvent, + IoTCoreThingTypeEvent, +) +from tests.functional.utils import load_event + + +def test_iot_core_thing_event(): + raw_event = load_event("iotRegistryEventsThingEvent.json") + parsed_event: IoTCoreThingEvent = IoTCoreThingEvent(**raw_event) + + assert parsed_event.event_id == raw_event["eventId"] + assert parsed_event.event_type == raw_event["eventType"] + convert_time = int(round(parsed_event.timestamp.timestamp() * 1000)) + assert convert_time == raw_event["timestamp"] + assert parsed_event.operation == raw_event["operation"] + assert parsed_event.account_id == raw_event["accountId"] + assert parsed_event.thing_id == raw_event["thingId"] + assert parsed_event.thing_name == raw_event["thingName"] + assert parsed_event.version_number == raw_event["versionNumber"] + assert parsed_event.thing_type_name == raw_event["thingTypeName"] + assert parsed_event.attributes == raw_event["attributes"] + + +def test_iot_core_thing_type_event(): + raw_event = load_event("iotRegistryEventsThingTypeEvent.json") + parsed_event: IoTCoreThingTypeEvent = IoTCoreThingTypeEvent(**raw_event) + + assert parsed_event.event_id == raw_event["eventId"] + assert parsed_event.event_type == raw_event["eventType"] + convert_time = int(round(parsed_event.timestamp.timestamp() * 1000)) + assert convert_time == raw_event["timestamp"] + assert parsed_event.operation == raw_event["operation"] + assert parsed_event.account_id == raw_event["accountId"] + assert parsed_event.thing_type_id == raw_event["thingTypeId"] + assert parsed_event.thing_type_name == raw_event["thingTypeName"] + assert parsed_event.is_deprecated == raw_event["isDeprecated"] + assert parsed_event.deprecation_date == raw_event["deprecationDate"] + assert parsed_event.searchable_attributes == raw_event["searchableAttributes"] + assert parsed_event.propagating_attributes == raw_event["propagatingAttributes"] + assert parsed_event.description == raw_event["description"] + + +def test_iot_core_thing_type_association_event(): + raw_event = load_event("iotRegistryEventsThingTypeAssociationEvent.json") + parsed_event: IoTCoreThingTypeAssociationEvent = IoTCoreThingTypeAssociationEvent(**raw_event) + + assert parsed_event.event_id == raw_event["eventId"] + assert parsed_event.event_type == raw_event["eventType"] + convert_time = int(round(parsed_event.timestamp.timestamp() * 1000)) + assert convert_time == raw_event["timestamp"] + assert parsed_event.operation == raw_event["operation"] + assert parsed_event.thing_id == raw_event["thingId"] + assert parsed_event.thing_name == raw_event["thingName"] + assert parsed_event.thing_type_name == raw_event["thingTypeName"] + + +def test_iot_core_thing_group_event(): + + raw_event = load_event("iotRegistryEventsThingGroupEvent.json") + parsed_event: IoTCoreThingGroupEvent = IoTCoreThingGroupEvent(**raw_event) + + assert parsed_event.event_id == raw_event["eventId"] + assert parsed_event.event_type == raw_event["eventType"] + convert_time = int(round(parsed_event.timestamp.timestamp() * 1000)) + assert convert_time == raw_event["timestamp"] + assert parsed_event.operation == raw_event["operation"] + assert parsed_event.account_id == raw_event["accountId"] + assert parsed_event.thing_group_name == raw_event["thingGroupName"] + assert parsed_event.version_number == raw_event["versionNumber"] + assert parsed_event.parent_group_name == raw_event["parentGroupName"] + assert parsed_event.parent_group_id == raw_event["parentGroupId"] + assert parsed_event.description == raw_event["description"] + assert parsed_event.root_to_parent_thing_groups == raw_event["rootToParentThingGroups"] + assert parsed_event.attributes == raw_event["attributes"] + assert parsed_event.dynamic_group_mapping_id == raw_event["dynamicGroupMappingId"] + + +def test_iot_core_add_or_remove_from_thing_group_event(): + + raw_event = load_event("iotRegistryEventsAddOrRemoveFromThingGroupEvent.json") + parsed_event: IoTCoreAddOrRemoveFromThingGroupEvent = IoTCoreAddOrRemoveFromThingGroupEvent(**raw_event) + + assert parsed_event.event_id == raw_event["eventId"] + assert parsed_event.event_type == raw_event["eventType"] + convert_time = int(round(parsed_event.timestamp.timestamp() * 1000)) + assert convert_time == raw_event["timestamp"] + assert parsed_event.operation == raw_event["operation"] + assert parsed_event.account_id == raw_event["accountId"] + assert parsed_event.group_arn == raw_event["groupArn"] + assert parsed_event.group_id == raw_event["groupId"] + assert parsed_event.thing_arn == raw_event["thingArn"] + assert parsed_event.thing_id == raw_event["thingId"] + assert parsed_event.membership_id == raw_event["membershipId"] + + +def test_iot_core_add_or_delete_from_thing_group_event(): + + raw_event = load_event("iotRegistryEventsAddOrDeleteFromThingGroupEvent.json") + parsed_event: IoTCoreAddOrDeleteFromThingGroupEvent = IoTCoreAddOrDeleteFromThingGroupEvent(**raw_event) + + assert parsed_event.event_id == raw_event["eventId"] + assert parsed_event.event_type == raw_event["eventType"] + convert_time = int(round(parsed_event.timestamp.timestamp() * 1000)) + assert convert_time == raw_event["timestamp"] + assert parsed_event.operation == raw_event["operation"] + assert parsed_event.account_id == raw_event["accountId"] + assert parsed_event.thing_group_id == raw_event["thingGroupId"] + assert parsed_event.thing_group_name == raw_event["thingGroupName"] + assert parsed_event.child_group_id == raw_event["childGroupId"] + assert parsed_event.child_group_name == raw_event["childGroupName"]