Skip to content

Commit

Permalink
feat(parser): Event source dataclasses for IoT Core Registry Events (#…
Browse files Browse the repository at this point in the history
…6123)

* Comment out fields to work with

* work on tests

* Add docs

* Add initial doc links

* work

* fix links

* Add github links

* work

* add files

* fill classes

* add log statement

* work

* apply suggestions

* Add examples for first items

* Fix documentation

* apply suggestion

* Add doc example

* Work

* work

* Adding more coverage + documentation

* Adding more coverage + documentation

* Adding more coverage + documentation

* Adding more coverage + documentation

* Adding more coverage + documentation

---------

Co-authored-by: Leandro Damascena <[email protected]>
  • Loading branch information
basvandriel and leandrodamascena authored Feb 25, 2025
1 parent 1258d6d commit 79d57d8
Show file tree
Hide file tree
Showing 10 changed files with 668 additions and 0 deletions.
418 changes: 418 additions & 0 deletions aws_lambda_powertools/utilities/data_classes/iot_registry_event.py

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions docs/utilities/data_classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ Each event source is linked to its corresponding GitHub file with the full set o
| [TransferFamilyAuthorizerResponse] | `TransferFamilyAuthorizerResponse` | [Github](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/transfer_family_event.py) |
| [VPC Lattice V2](#vpc-lattice-v2) | `VPCLatticeV2Event` | [Github](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py) |
| [VPC Lattice V1](#vpc-lattice-v1) | `VPCLatticeEvent` | [Github](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py) |
| [IoT Core Thing Created/Updated/Deleted](#iot-core-thing-createdupdateddeleted) | `IoTCoreThingEvent` | [GitHub](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/iot_registry_event.py#L33) |
| [IoT Core Thing Type Created/Updated/Deprecated/Undeprecated/Deleted](#iot-core-thing-type-createdupdateddeprecatedundeprecateddeleted) | `IoTCoreThingTypeEvent` | [GitHub](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/iot_registry_event.py#L96) |
| [IoT Core Thing Type Associated/Disassociated with a Thing](#iot-core-thing-type-associateddisassociated-with-a-thing) | `IoTCoreThingTypeAssociationEvent` | [GitHub](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/iot_registry_event.py#L173) |
| [IoT Core Thing Group Created/Updated/Deleted](#iot-core-thing-group-createdupdateddeleted) | `IoTCoreThingGroupEvent` | [GitHub](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/iot_registry_event.py#L214) |
| [IoT Thing Added/Removed from Thing Group](#iot-thing-addedremoved-from-thing-group) | `IoTCoreAddOrRemoveFromThingGroupEvent` | [GitHub](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/iot_registry_event.py#L304) |
| [IoT Child Group Added/Deleted from Parent Group](#iot-child-group-addeddeleted-from-parent-group) | `IoTCoreAddOrDeleteFromThingGroupEvent` | [GitHub](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/aws_lambda_powertools/utilities/data_classes/iot_registry_event.py#L366) |

???+ info
The examples showcase a subset of Event Source Data Classes capabilities - for comprehensive details, leverage your IDE's
Expand Down Expand Up @@ -811,6 +817,92 @@ You can register your Lambda functions as targets within an Amazon VPC Lattice s
--8<-- "examples/event_sources/events/vpc_lattice_payload.json"
```

### IoT Core Events

#### IoT Core Thing Created/Updated/Deleted

You can use IoT Core registry events to trigger your lambda functions. More information on this specific one can be found [here](https://docs.aws.amazon.com/iot/latest/developerguide/registry-events.html#registry-events-thing).

=== "app.py"
```python hl_lines="2 5"
--8<-- "examples/event_sources/src/iot_registry_thing_event.py"
```

=== "Example Event"
```json
--8<-- "tests/events/iotRegistryEventsThingEvent.json"
```

#### IoT Core Thing Type Created/Updated/Deprecated/Undeprecated/Deleted

You can use IoT Core registry events to trigger your lambda functions. More information on this specific one can be found [here](https://docs.aws.amazon.com/iot/latest/developerguide/registry-events.html#registry-events-thingtype-crud).

=== "app.py"
```python hl_lines="2 5"
--8<-- "examples/event_sources/src/iot_registry_thing_type_event.py"
```

=== "Example Event"
```json
--8<-- "tests/events/iotRegistryEventsThingTypeEvent.json"
```

#### IoT Core Thing Type Associated/Disassociated with a Thing

You can use IoT Core registry events to trigger your lambda functions. More information on this specific one can be found [here](https://docs.aws.amazon.com/iot/latest/developerguide/registry-events.html#registry-events-thingtype-assoc).

=== "app.py"
```python hl_lines="2 5"
--8<-- "examples/event_sources/src/iot_registry_thing_type_association_event.py"
```

=== "Example Event"
```json
--8<-- "tests/events/iotRegistryEventsThingTypeAssociationEvent.json"
```

#### IoT Core Thing Group Created/Updated/Deleted

You can use IoT Core registry events to trigger your lambda functions. More information on this specific one can be found [here](https://docs.aws.amazon.com/iot/latest/developerguide/registry-events.html#registry-events-thinggroup-crud).

=== "app.py"
```python hl_lines="2 5"
--8<-- "examples/event_sources/src/iot_registry_thing_group_event.py"
```

=== "Example Event"
```json
--8<-- "tests/events/iotRegistryEventsThingGroupEvent.json"
```

#### IoT Thing Added/Removed from Thing Group

You can use IoT Core registry events to trigger your lambda functions. More information on this specific one can be found [here](https://docs.aws.amazon.com/iot/latest/developerguide/registry-events.html#registry-events-thinggroup-addremove).

=== "app.py"
```python hl_lines="2 5"
--8<-- "examples/event_sources/src/iot_registry_add_or_remove_from_thing_group_event.py"
```

=== "Example Event"
```json
--8<-- "tests/events/iotRegistryEventsAddOrRemoveFromThingGroupEvent.json"
```

#### IoT Child Group Added/Deleted from Parent Group

You can use IoT Core registry events to trigger your lambda functions. More information on this specific one can be found [here](https://docs.aws.amazon.com/iot/latest/developerguide/registry-events.html#registry-events-thinggroup-adddelete).

=== "app.py"
```python hl_lines="2 5"
--8<-- "examples/event_sources/src/iot_registry_add_or_delete_from_thing_group_event.py"
```

=== "Example Event"
```json
--8<-- "tests/events/iotRegistryEventsAddOrDeleteFromThingGroupEvent.json"
```

## Advanced

### Debugging
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.iot_registry_event import IoTCoreAddOrDeleteFromThingGroupEvent


@event_source(data_class=IoTCoreAddOrDeleteFromThingGroupEvent)
def lambda_handler(event: IoTCoreAddOrDeleteFromThingGroupEvent, context):
print(f"Received IoT Core event type {event.event_type}")
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.iot_registry_event import IoTCoreAddOrRemoveFromThingGroupEvent


@event_source(data_class=IoTCoreAddOrRemoveFromThingGroupEvent)
def lambda_handler(event: IoTCoreAddOrRemoveFromThingGroupEvent, context):
print(f"Received IoT Core event type {event.event_type}")
7 changes: 7 additions & 0 deletions examples/event_sources/src/iot_registry_thing_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.iot_registry_event import IoTCoreThingEvent


@event_source(data_class=IoTCoreThingEvent)
def lambda_handler(event: IoTCoreThingEvent, context):
print(f"Received IoT Core event type {event.event_type}")
7 changes: 7 additions & 0 deletions examples/event_sources/src/iot_registry_thing_group_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.iot_registry_event import IoTCoreThingGroupEvent


@event_source(data_class=IoTCoreThingGroupEvent)
def lambda_handler(event: IoTCoreThingGroupEvent, context):
print(f"Received IoT Core event type {event.event_type}")
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.iot_registry_event import IoTCoreThingTypeAssociationEvent


@event_source(data_class=IoTCoreThingTypeAssociationEvent)
def lambda_handler(event: IoTCoreThingTypeAssociationEvent, context):
print(f"Received IoT Core event type {event.event_type}")
7 changes: 7 additions & 0 deletions examples/event_sources/src/iot_registry_thing_type_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.iot_registry_event import IoTCoreThingTypeEvent


@event_source(data_class=IoTCoreThingTypeEvent)
def lambda_handler(event: IoTCoreThingTypeEvent, context):
print(f"Received IoT Core event type {event.event_type}")
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ def handler(event, context):
assert "stack_trace" not in log


@pytest.mark.skipif(reason="Test temporarily disabled")
def test_thread_safe_keys_encapsulation(service_name, stdout):
logger = Logger(
service=service_name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from datetime import datetime

from aws_lambda_powertools.utilities.data_classes.iot_registry_event import (
IoTCoreAddOrDeleteFromThingGroupEvent,
IoTCoreAddOrRemoveFromThingGroupEvent,
IoTCoreThingEvent,
IoTCoreThingGroupEvent,
IoTCoreThingTypeAssociationEvent,
IoTCoreThingTypeEvent,
)
from tests.functional.utils import load_event


def test_iotcore_thing_event():
raw_event = load_event("iotRegistryEventsThingEvent.json")
parsed_event = IoTCoreThingEvent(raw_event)

assert parsed_event.event_type == raw_event["eventType"]
assert parsed_event.operation == raw_event["operation"]
assert parsed_event.thing_id == raw_event["thingId"]
assert parsed_event.account_id == raw_event["accountId"]
assert parsed_event.thing_name == raw_event["thingName"]
assert parsed_event.version_number == raw_event["versionNumber"]
assert parsed_event.thing_type_name == raw_event.get("thingTypeName")
assert parsed_event.attributes == raw_event["attributes"]
assert parsed_event.event_id == raw_event["eventId"]

# Validate timestamp conversion
# Original field is int
expected_timestamp = datetime.fromtimestamp(
raw_event["timestamp"] / 1000 if raw_event["timestamp"] > 10**10 else raw_event["timestamp"],
)
assert parsed_event.timestamp == expected_timestamp


def test_iotcore_thing_type_event():
raw_event = load_event("iotRegistryEventsThingTypeEvent.json")
parsed_event = IoTCoreThingTypeEvent(raw_event)

assert parsed_event.event_type == raw_event["eventType"]
assert parsed_event.operation == raw_event["operation"]
assert parsed_event.event_id == raw_event["eventId"]
assert parsed_event.account_id == raw_event["accountId"]
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"]
assert parsed_event.thing_type_id == raw_event["thingTypeId"]


def test_iotcore_thing_type_association_event():
raw_event = load_event("iotRegistryEventsThingTypeAssociationEvent.json")
parsed_event = IoTCoreThingTypeAssociationEvent(raw_event)

assert parsed_event.event_type == raw_event["eventType"]
assert parsed_event.operation == raw_event["operation"]
assert parsed_event.event_id == raw_event["eventId"]
assert parsed_event.thing_id == raw_event["thingId"]
assert parsed_event.thing_type_name == raw_event["thingTypeName"]
assert parsed_event.thing_name == raw_event["thingName"]


def test_iotcore_thing_group_event():
raw_event = load_event("iotRegistryEventsThingGroupEvent.json")
parsed_event = IoTCoreThingGroupEvent(raw_event)

assert parsed_event.event_type == raw_event["eventType"]
assert parsed_event.event_id == raw_event["eventId"]
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.thing_group_id == raw_event["thingGroupId"]
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_iotcore_add_or_remove_from_thing_group_event():
raw_event = load_event("iotRegistryEventsAddOrRemoveFromThingGroupEvent.json")
parsed_event = IoTCoreAddOrRemoveFromThingGroupEvent(raw_event)

assert parsed_event.event_type == raw_event["eventType"]
assert parsed_event.operation == raw_event["operation"]
assert parsed_event.account_id == raw_event["accountId"]
assert parsed_event.event_id == raw_event["eventId"]
assert parsed_event.group_id == raw_event["groupId"]
assert parsed_event.group_arn == raw_event["groupArn"]
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_iotcore_add_or_delete_from_thing_group_event():
raw_event = load_event("iotRegistryEventsAddOrDeleteFromThingGroupEvent.json")
parsed_event = IoTCoreAddOrDeleteFromThingGroupEvent(raw_event)

assert parsed_event.event_type == raw_event["eventType"]
assert parsed_event.event_id == raw_event["eventId"]
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"]
assert parsed_event.operation == raw_event["operation"]

expected_timestamp = datetime.fromtimestamp(
raw_event["timestamp"] / 1000 if raw_event["timestamp"] > 10**10 else raw_event["timestamp"],
)
assert parsed_event.timestamp == expected_timestamp

0 comments on commit 79d57d8

Please sign in to comment.