modmex-lambda 0.2.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modmex_lambda/__init__.py +20 -11
- modmex_lambda/connectors/__init__.py +28 -0
- modmex_lambda/connectors/cloudwatch.py +17 -0
- modmex_lambda/connectors/dynamodb.py +123 -0
- modmex_lambda/connectors/eventbridge.py +19 -0
- modmex_lambda/connectors/icloudwatch.py +14 -0
- modmex_lambda/connectors/idynamodb.py +68 -0
- modmex_lambda/connectors/ieventbridge.py +14 -0
- modmex_lambda/connectors/ilambda.py +14 -0
- modmex_lambda/connectors/is3.py +30 -0
- modmex_lambda/connectors/isns.py +20 -0
- modmex_lambda/connectors/isqs.py +21 -0
- modmex_lambda/connectors/lambda_.py +17 -0
- modmex_lambda/connectors/module.py +67 -0
- modmex_lambda/connectors/s3.py +43 -0
- modmex_lambda/connectors/sns.py +31 -0
- modmex_lambda/connectors/sqs.py +31 -0
- modmex_lambda/data_classes/__init__.py +107 -24
- modmex_lambda/dependencies.py +106 -0
- modmex_lambda/event_handler/__init__.py +11 -10
- modmex_lambda/event_handler/api_gateway.py +7 -7
- modmex_lambda/event_handler/dependencies/__init__.py +30 -6
- modmex_lambda/event_handler/dependencies/depends.py +4 -52
- modmex_lambda/event_handler/routing.py +43 -1
- modmex_lambda/event_handler/types.py +1 -1
- modmex_lambda/logging.py +48 -14
- modmex_lambda/stream/__init__.py +3 -0
- modmex_lambda/stream/events/__init__.py +0 -0
- modmex_lambda/stream/events/dynamodb.py +123 -0
- modmex_lambda/stream/events/kinesis.py +44 -0
- modmex_lambda/stream/events/s3.py +66 -0
- modmex_lambda/stream/events/sns.py +54 -0
- modmex_lambda/stream/events/sqs.py +46 -0
- modmex_lambda/stream/filters/__init__.py +0 -0
- modmex_lambda/stream/filters/content.py +9 -0
- modmex_lambda/stream/filters/event_type.py +17 -0
- modmex_lambda/stream/filters/latch.py +21 -0
- modmex_lambda/stream/filters/skip.py +18 -0
- modmex_lambda/stream/flavors/__init__.py +0 -0
- modmex_lambda/stream/flavors/base_flavor.py +140 -0
- modmex_lambda/stream/flavors/cdc.py +70 -0
- modmex_lambda/stream/flavors/collect.py +105 -0
- modmex_lambda/stream/flavors/correlate.py +114 -0
- modmex_lambda/stream/flavors/evaluate.py +235 -0
- modmex_lambda/stream/flavors/expired.py +104 -0
- modmex_lambda/stream/flavors/iflavor.py +19 -0
- modmex_lambda/stream/flavors/job.py +294 -0
- modmex_lambda/stream/flavors/materialize.py +65 -0
- modmex_lambda/stream/flavors/s3.py +63 -0
- modmex_lambda/stream/flavors/sns.py +59 -0
- modmex_lambda/stream/flavors/task.py +135 -0
- modmex_lambda/stream/flavors/update.py +171 -0
- modmex_lambda/stream/irules_registry.py +18 -0
- modmex_lambda/stream/operators/__init__.py +1 -0
- modmex_lambda/stream/operators/cloudwatch.py +29 -0
- modmex_lambda/stream/operators/dynamodb.py +391 -0
- modmex_lambda/stream/operators/ioperator.py +14 -0
- modmex_lambda/stream/operators/lambda_.py +29 -0
- modmex_lambda/stream/operators/publisher.py +99 -0
- modmex_lambda/stream/operators/s3.py +131 -0
- modmex_lambda/stream/operators/sns.py +58 -0
- modmex_lambda/stream/operators/sqs.py +83 -0
- modmex_lambda/stream/rules_registry.py +38 -0
- modmex_lambda/stream/runner.py +93 -0
- modmex_lambda/stream/sources/__init__.py +53 -0
- modmex_lambda/stream/sources/base.py +60 -0
- modmex_lambda/stream/sources/dynamodb.py +71 -0
- modmex_lambda/stream/sources/kinesis.py +51 -0
- modmex_lambda/stream/sources/s3.py +51 -0
- modmex_lambda/stream/sources/sns.py +51 -0
- modmex_lambda/stream/sources/sqs.py +51 -0
- modmex_lambda/stream/utils/__init__.py +0 -0
- modmex_lambda/stream/utils/apigateway.py +41 -0
- modmex_lambda/stream/utils/aws.py +6 -0
- modmex_lambda/stream/utils/batch.py +9 -0
- modmex_lambda/stream/utils/cloudwatch.py +11 -0
- modmex_lambda/stream/utils/concurrency.py +54 -0
- modmex_lambda/stream/utils/contracts.py +45 -0
- modmex_lambda/stream/utils/data_classes/__init__.py +0 -0
- modmex_lambda/stream/utils/data_classes/dynamodb.py +17 -0
- modmex_lambda/stream/utils/decorators.py +9 -0
- modmex_lambda/stream/utils/dynamodb.py +140 -0
- modmex_lambda/stream/utils/eventbridge.py +25 -0
- modmex_lambda/stream/utils/faults.py +100 -0
- modmex_lambda/stream/utils/filters.py +15 -0
- modmex_lambda/stream/utils/json_encoder.py +12 -0
- modmex_lambda/stream/utils/lambda_.py +11 -0
- modmex_lambda/stream/utils/operators.py +76 -0
- modmex_lambda/stream/utils/opt.py +15 -0
- modmex_lambda/stream/utils/pluralize.py +13 -0
- modmex_lambda/stream/utils/print.py +24 -0
- modmex_lambda/stream/utils/retry.py +28 -0
- modmex_lambda/stream/utils/s3.py +52 -0
- modmex_lambda/stream/utils/sns.py +11 -0
- modmex_lambda/stream/utils/split.py +32 -0
- modmex_lambda/stream/utils/sqs.py +19 -0
- modmex_lambda/stream/utils/tags.py +33 -0
- modmex_lambda/stream/utils/time.py +17 -0
- modmex_lambda/stream/utils/uow.py +110 -0
- modmex_lambda-0.4.0.dist-info/METADATA +1107 -0
- modmex_lambda-0.4.0.dist-info/RECORD +138 -0
- modmex_lambda-0.2.0.dist-info/METADATA +0 -446
- modmex_lambda-0.2.0.dist-info/RECORD +0 -48
- {modmex_lambda-0.2.0.dist-info → modmex_lambda-0.4.0.dist-info}/WHEEL +0 -0
- {modmex_lambda-0.2.0.dist-info → modmex_lambda-0.4.0.dist-info}/licenses/LICENSE +0 -0
modmex_lambda/__init__.py
CHANGED
|
@@ -7,51 +7,60 @@ from typing import TYPE_CHECKING, Any
|
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from .event_handler import (
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
APIGatewayHttpResolver,
|
|
11
|
+
APIGatewayRestResolver,
|
|
12
12
|
Response,
|
|
13
13
|
)
|
|
14
14
|
from .event_handler.request import Request
|
|
15
15
|
from .event_sources import event_source
|
|
16
|
-
from .
|
|
16
|
+
from .connectors import AwsConnectorsModule
|
|
17
|
+
from .dependencies import (
|
|
17
18
|
DefaultDependencyResolver,
|
|
18
19
|
DependencyResolver,
|
|
19
|
-
Depends,
|
|
20
20
|
InjectorDependencyResolver,
|
|
21
|
+
create_dependency_resolver,
|
|
22
|
+
default_dependency_resolver,
|
|
21
23
|
)
|
|
24
|
+
from .event_handler.dependencies.depends import Depends
|
|
22
25
|
from .logging import Logger
|
|
23
26
|
from .parser import event_parser, parse
|
|
24
27
|
from .validation import ModmexValidator, ValidationError
|
|
25
28
|
|
|
26
29
|
_EXPORTS = {
|
|
27
|
-
"
|
|
28
|
-
"
|
|
30
|
+
"APIGatewayHttpResolver": ("modmex_lambda.event_handler", "APIGatewayHttpResolver"),
|
|
31
|
+
"APIGatewayRestResolver": ("modmex_lambda.event_handler", "APIGatewayRestResolver"),
|
|
29
32
|
"Request": ("modmex_lambda.event_handler.request", "Request"),
|
|
30
33
|
"Response": ("modmex_lambda.event_handler", "Response"),
|
|
31
34
|
"parse": ("modmex_lambda.parser", "parse"),
|
|
32
35
|
"event_parser": ("modmex_lambda.parser", "event_parser"),
|
|
33
36
|
"event_source": ("modmex_lambda.event_sources", "event_source"),
|
|
34
|
-
"
|
|
35
|
-
"
|
|
37
|
+
"AwsConnectorsModule": ("modmex_lambda.connectors", "AwsConnectorsModule"),
|
|
38
|
+
"DefaultDependencyResolver": ("modmex_lambda.dependencies", "DefaultDependencyResolver"),
|
|
39
|
+
"DependencyResolver": ("modmex_lambda.dependencies", "DependencyResolver"),
|
|
36
40
|
"Depends": ("modmex_lambda.event_handler.dependencies.depends", "Depends"),
|
|
37
|
-
"InjectorDependencyResolver": ("modmex_lambda.
|
|
41
|
+
"InjectorDependencyResolver": ("modmex_lambda.dependencies", "InjectorDependencyResolver"),
|
|
42
|
+
"create_dependency_resolver": ("modmex_lambda.dependencies", "create_dependency_resolver"),
|
|
43
|
+
"default_dependency_resolver": ("modmex_lambda.dependencies", "default_dependency_resolver"),
|
|
38
44
|
"Logger": ("modmex_lambda.logging", "Logger"),
|
|
39
45
|
"ModmexValidator": ("modmex_lambda.validation", "ModmexValidator"),
|
|
40
46
|
"ValidationError": ("modmex_lambda.validation", "ValidationError"),
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
__all__ = [
|
|
44
|
-
"
|
|
45
|
-
"
|
|
50
|
+
"APIGatewayHttpResolver",
|
|
51
|
+
"APIGatewayRestResolver",
|
|
46
52
|
"Request",
|
|
47
53
|
"Response",
|
|
48
54
|
"parse",
|
|
49
55
|
"event_parser",
|
|
50
56
|
"event_source",
|
|
57
|
+
"AwsConnectorsModule",
|
|
51
58
|
"DefaultDependencyResolver",
|
|
52
59
|
"DependencyResolver",
|
|
53
60
|
"Depends",
|
|
54
61
|
"InjectorDependencyResolver",
|
|
62
|
+
"create_dependency_resolver",
|
|
63
|
+
"default_dependency_resolver",
|
|
55
64
|
"Logger",
|
|
56
65
|
"ModmexValidator",
|
|
57
66
|
"ValidationError",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from modmex_lambda.connectors.module import AwsConnectorsModule
|
|
8
|
+
|
|
9
|
+
_EXPORTS = {
|
|
10
|
+
"AwsConnectorsModule": ("modmex_lambda.connectors.module", "AwsConnectorsModule"),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
__all__ = ["AwsConnectorsModule"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def __getattr__(name: str) -> Any:
|
|
17
|
+
target = _EXPORTS.get(name)
|
|
18
|
+
if target is None:
|
|
19
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
20
|
+
|
|
21
|
+
module_name, attr = target
|
|
22
|
+
value = getattr(import_module(module_name), attr)
|
|
23
|
+
globals()[name] = value
|
|
24
|
+
return value
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def __dir__() -> list[str]:
|
|
28
|
+
return sorted([*globals().keys(), *__all__])
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from modmex_lambda.connectors.icloudwatch import ICloudWatchConnector
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Connector(ICloudWatchConnector):
|
|
5
|
+
|
|
6
|
+
def __init__(self, client = None) -> None:
|
|
7
|
+
self._client = client
|
|
8
|
+
|
|
9
|
+
@property
|
|
10
|
+
def client(self):
|
|
11
|
+
if not self._client:
|
|
12
|
+
import boto3
|
|
13
|
+
self._client = boto3.client('cloudwatch')
|
|
14
|
+
return self._client
|
|
15
|
+
|
|
16
|
+
def put(self, input_params):
|
|
17
|
+
return self.client.put_metric_data(**input_params)
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from functools import reduce
|
|
2
|
+
from typing import Iterable
|
|
3
|
+
|
|
4
|
+
from modmex_lambda.connectors.idynamodb import IDynamodbConnector
|
|
5
|
+
from modmex_lambda.stream.utils.retry import (
|
|
6
|
+
assert_max_retries,
|
|
7
|
+
DEFAULT_RETRY_CONFIG,
|
|
8
|
+
wait,
|
|
9
|
+
get_delay
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Connector(IDynamodbConnector):
|
|
14
|
+
|
|
15
|
+
def __init__(self,# pylint: disable=W0102
|
|
16
|
+
table_name = 'undefined',
|
|
17
|
+
retry_config = DEFAULT_RETRY_CONFIG,
|
|
18
|
+
client = None) -> None:
|
|
19
|
+
self.table_name = table_name
|
|
20
|
+
self._client = client
|
|
21
|
+
self.retry_config = retry_config
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def client(self):
|
|
25
|
+
if not self._client:
|
|
26
|
+
import boto3
|
|
27
|
+
self._client = boto3.resource('dynamodb')
|
|
28
|
+
return self._client
|
|
29
|
+
|
|
30
|
+
def get(self, input_params):
|
|
31
|
+
return self.client.Table(self.table_name).get_item(
|
|
32
|
+
**input_params
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def update(self, input_params):
|
|
36
|
+
return self.client.Table(self.table_name).update_item(
|
|
37
|
+
**input_params
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def put(self, input_params):
|
|
41
|
+
return self.client.Table(self.table_name).put_item(
|
|
42
|
+
**input_params
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def query(self, input_params):
|
|
46
|
+
return self.client.Table(self.table_name).query(
|
|
47
|
+
**input_params
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def query_page(self, input_params):
|
|
51
|
+
return self.query(input_params)
|
|
52
|
+
|
|
53
|
+
def scan(self, input_params):
|
|
54
|
+
return self.client.Table(self.table_name).scan(
|
|
55
|
+
**input_params
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def query_all(self, input_params):
|
|
59
|
+
items = []
|
|
60
|
+
while True:
|
|
61
|
+
|
|
62
|
+
result = self.client.Table(self.table_name).query(
|
|
63
|
+
**input_params
|
|
64
|
+
)
|
|
65
|
+
for item in result['Items']:
|
|
66
|
+
items.append(item)
|
|
67
|
+
|
|
68
|
+
if 'LastEvaluatedKey' in result and result['LastEvaluatedKey']:
|
|
69
|
+
input_params['ExclusiveStartKey'] = result['LastEvaluatedKey']
|
|
70
|
+
else:
|
|
71
|
+
break
|
|
72
|
+
return items
|
|
73
|
+
|
|
74
|
+
def batch_get(self, input_params):
|
|
75
|
+
return self._batch_get(input_params, [])
|
|
76
|
+
|
|
77
|
+
def _batch_get(self, params, attempts):
|
|
78
|
+
assert_max_retries(attempts, self.retry_config['max_retries'])
|
|
79
|
+
wait(get_delay(self.retry_config['retry_wait'], len(attempts)))
|
|
80
|
+
resp = self.client.batch_get_item(**params)
|
|
81
|
+
if 'UnprocessedKeys' in resp and resp['UnprocessedKeys']:
|
|
82
|
+
return self._batch_get(
|
|
83
|
+
unprocessed(params, resp),
|
|
84
|
+
[*attempts, resp]
|
|
85
|
+
)
|
|
86
|
+
return accumulate(attempts, resp)
|
|
87
|
+
|
|
88
|
+
def bulk_insert(self, items: Iterable):
|
|
89
|
+
with self.client.Table(self.table_name).batch_writer() as batch:
|
|
90
|
+
for item in items:
|
|
91
|
+
batch.put_item(Item=item)
|
|
92
|
+
|
|
93
|
+
def bulk_delete(self, items: Iterable):
|
|
94
|
+
with self.client.Table(self.table_name).batch_writer() as batch:
|
|
95
|
+
for key in items:
|
|
96
|
+
batch.delete_item(Key=key)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def unprocessed(params, resp):
|
|
100
|
+
return {
|
|
101
|
+
**params,
|
|
102
|
+
'RequestItems': resp['UnprocessedKeys']
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
def accumulate(attempts, resp):
|
|
106
|
+
def reducer(a, c):
|
|
107
|
+
return {
|
|
108
|
+
**a,
|
|
109
|
+
'Responses': reduce(
|
|
110
|
+
lambda a2, c2: {
|
|
111
|
+
**a2,
|
|
112
|
+
c2: [
|
|
113
|
+
*a2.get(c2, []),
|
|
114
|
+
*a['Responses'].get(c2, [])
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
list(a['Responses']),
|
|
118
|
+
{**c['Responses']}
|
|
119
|
+
),
|
|
120
|
+
'attempts': [*attempts, resp]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return reduce(reducer, reversed(attempts), resp)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
from modmex_lambda.connectors.ieventbridge import IEventBridgeConnector
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Connector(IEventBridgeConnector):
|
|
6
|
+
|
|
7
|
+
def __init__(self, client = None) -> None:
|
|
8
|
+
self._client = client
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def client(self):
|
|
12
|
+
if not self._client:
|
|
13
|
+
import boto3
|
|
14
|
+
self._client = boto3.client('events')
|
|
15
|
+
return self._client
|
|
16
|
+
|
|
17
|
+
def put_events(self, params):
|
|
18
|
+
response = self.client.put_events(**params)
|
|
19
|
+
return response
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ICloudWatchConnector(ABC):
|
|
6
|
+
@property
|
|
7
|
+
def client(self) -> Any:
|
|
8
|
+
"""Returns the CloudWatch client"""
|
|
9
|
+
raise NotImplementedError("client property must be implemented")
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def put(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
13
|
+
"""Puts metric data into CloudWatch"""
|
|
14
|
+
raise NotImplementedError("put method must be implemented")
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict, Iterable
|
|
3
|
+
|
|
4
|
+
class IDynamodbConnector(ABC):
|
|
5
|
+
table_name: str
|
|
6
|
+
retry_config: Dict[str, Any]
|
|
7
|
+
|
|
8
|
+
@property
|
|
9
|
+
def client(self) -> Any:
|
|
10
|
+
"""Returns the DynamoDB resource"""
|
|
11
|
+
raise NotImplementedError("client property must be implemented")
|
|
12
|
+
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def get(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
15
|
+
"""Retrieves an item from the table"""
|
|
16
|
+
raise NotImplementedError("get method must be implemented")
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def update(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
20
|
+
"""Updates an item in the table"""
|
|
21
|
+
raise NotImplementedError("update method must be implemented")
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def put(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
25
|
+
"""Puts an item into the table"""
|
|
26
|
+
raise NotImplementedError("put method must be implemented")
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def query(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
30
|
+
"""Queries items from the table"""
|
|
31
|
+
raise NotImplementedError("query method must be implemented")
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def query_all(self, input_params: Dict[str, Any]) -> list[Dict[str, Any]]:
|
|
35
|
+
"""Queries all items, handling pagination"""
|
|
36
|
+
raise NotImplementedError("query_all method must be implemented")
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def query_page(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
40
|
+
"""Queries one page of items"""
|
|
41
|
+
raise NotImplementedError("query_page method must be implemented")
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def scan(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
45
|
+
"""Scans one page of items"""
|
|
46
|
+
raise NotImplementedError("scan method must be implemented")
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def batch_get(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
50
|
+
"""Performs a batch get operation"""
|
|
51
|
+
raise NotImplementedError("batch_get method must be implemented")
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def bulk_insert(self, items: Iterable[Dict[str, Any]]) -> None:
|
|
55
|
+
"""Inserts multiple items using batch writer"""
|
|
56
|
+
raise NotImplementedError("bulk_insert method must be implemented")
|
|
57
|
+
|
|
58
|
+
@abstractmethod
|
|
59
|
+
def bulk_delete(self, items: Iterable[Dict[str, Any]]) -> None:
|
|
60
|
+
"""Deletes multiple items using batch writer"""
|
|
61
|
+
raise NotImplementedError("bulk_delete method must be implemented")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class DynamoDbResource(ABC):
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def Table(self, name: str):
|
|
68
|
+
raise NotImplementedError()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
class IEventBridgeConnector(ABC):
|
|
5
|
+
|
|
6
|
+
@property
|
|
7
|
+
def client(self) -> Any:
|
|
8
|
+
"""Returns the EventBridge client"""
|
|
9
|
+
raise NotImplementedError("client property must be implemented")
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def put_events(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
13
|
+
"""Puts events into EventBridge"""
|
|
14
|
+
raise NotImplementedError("put_events method must be implemented")
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ILambdaConnector(ABC):
|
|
6
|
+
@property
|
|
7
|
+
def client(self) -> Any:
|
|
8
|
+
"""Returns the Lambda client"""
|
|
9
|
+
raise NotImplementedError("client property must be implemented")
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def invoke(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
13
|
+
"""Invokes a Lambda function"""
|
|
14
|
+
raise NotImplementedError("invoke method must be implemented")
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
class IS3Connector(ABC):
|
|
5
|
+
bucket_name: str
|
|
6
|
+
|
|
7
|
+
@property
|
|
8
|
+
def client(self) -> Any:
|
|
9
|
+
"""Returns the S3 client"""
|
|
10
|
+
raise NotImplementedError("client property must be implemented")
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def put_object(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
14
|
+
"""Uploads an object to the bucket"""
|
|
15
|
+
raise NotImplementedError("put_object method must be implemented")
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def get_object(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
19
|
+
"""Retrieves an object from the bucket"""
|
|
20
|
+
raise NotImplementedError("get_object method must be implemented")
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def list_objects(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
24
|
+
"""Lists objects in the bucket"""
|
|
25
|
+
raise NotImplementedError("list_objects method must be implemented")
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def delete_object(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
29
|
+
"""Deletes an object from the bucket"""
|
|
30
|
+
raise NotImplementedError("delete_object method must be implemented")
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
class ISNSConnector(ABC):
|
|
5
|
+
topic_arn: str
|
|
6
|
+
|
|
7
|
+
@property
|
|
8
|
+
def client(self) -> Any:
|
|
9
|
+
"""Returns the SNS client"""
|
|
10
|
+
raise NotImplementedError("client property must be implemented")
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def publish(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
14
|
+
"""Publishes a message to the SNS topic"""
|
|
15
|
+
raise NotImplementedError("publish method must be implemented")
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def publish_batch(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
19
|
+
"""Publishes a batch of messages to the SNS topic"""
|
|
20
|
+
raise NotImplementedError("publish_batch method must be implemented")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ISQSConnector(ABC):
|
|
6
|
+
queue_url: str
|
|
7
|
+
|
|
8
|
+
@property
|
|
9
|
+
def client(self) -> Any:
|
|
10
|
+
"""Returns the SQS client"""
|
|
11
|
+
raise NotImplementedError("client property must be implemented")
|
|
12
|
+
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def send_message(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
15
|
+
"""Sends a message to SQS"""
|
|
16
|
+
raise NotImplementedError("send_message method must be implemented")
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def send_message_batch(self, input_params: Dict[str, Any]) -> Dict[str, Any]:
|
|
20
|
+
"""Sends a message batch to SQS"""
|
|
21
|
+
raise NotImplementedError("send_message_batch method must be implemented")
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from modmex_lambda.connectors.ilambda import ILambdaConnector
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Connector(ILambdaConnector):
|
|
5
|
+
|
|
6
|
+
def __init__(self, client = None) -> None:
|
|
7
|
+
self._client = client
|
|
8
|
+
|
|
9
|
+
@property
|
|
10
|
+
def client(self):
|
|
11
|
+
if not self._client:
|
|
12
|
+
import boto3
|
|
13
|
+
self._client = boto3.client('lambda')
|
|
14
|
+
return self._client
|
|
15
|
+
|
|
16
|
+
def invoke(self, params):
|
|
17
|
+
return self.client.invoke(**params)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Injector module with default AWS connector bindings."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from injector import Module, provider, singleton
|
|
6
|
+
|
|
7
|
+
from modmex_lambda.connectors.icloudwatch import ICloudWatchConnector
|
|
8
|
+
from modmex_lambda.connectors.idynamodb import IDynamodbConnector
|
|
9
|
+
from modmex_lambda.connectors.ieventbridge import IEventBridgeConnector
|
|
10
|
+
from modmex_lambda.connectors.ilambda import ILambdaConnector
|
|
11
|
+
from modmex_lambda.connectors.is3 import IS3Connector
|
|
12
|
+
from modmex_lambda.connectors.isns import ISNSConnector
|
|
13
|
+
from modmex_lambda.connectors.isqs import ISQSConnector
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AwsConnectorsModule(Module):
|
|
17
|
+
@singleton
|
|
18
|
+
@provider
|
|
19
|
+
def provide_dynamodb(self) -> IDynamodbConnector:
|
|
20
|
+
from modmex_lambda.connectors.dynamodb import Connector
|
|
21
|
+
|
|
22
|
+
return Connector()
|
|
23
|
+
|
|
24
|
+
@singleton
|
|
25
|
+
@provider
|
|
26
|
+
def provide_cloudwatch(self) -> ICloudWatchConnector:
|
|
27
|
+
from modmex_lambda.connectors.cloudwatch import Connector
|
|
28
|
+
|
|
29
|
+
return Connector()
|
|
30
|
+
|
|
31
|
+
@singleton
|
|
32
|
+
@provider
|
|
33
|
+
def provide_eventbridge(self) -> IEventBridgeConnector:
|
|
34
|
+
from modmex_lambda.connectors.eventbridge import Connector
|
|
35
|
+
|
|
36
|
+
return Connector()
|
|
37
|
+
|
|
38
|
+
@singleton
|
|
39
|
+
@provider
|
|
40
|
+
def provide_lambda(self) -> ILambdaConnector:
|
|
41
|
+
from modmex_lambda.connectors.lambda_ import Connector
|
|
42
|
+
|
|
43
|
+
return Connector()
|
|
44
|
+
|
|
45
|
+
@singleton
|
|
46
|
+
@provider
|
|
47
|
+
def provide_s3(self) -> IS3Connector:
|
|
48
|
+
from modmex_lambda.connectors.s3 import Connector
|
|
49
|
+
|
|
50
|
+
return Connector(None)
|
|
51
|
+
|
|
52
|
+
@singleton
|
|
53
|
+
@provider
|
|
54
|
+
def provide_sns(self) -> ISNSConnector:
|
|
55
|
+
from modmex_lambda.connectors.sns import Connector
|
|
56
|
+
|
|
57
|
+
return Connector()
|
|
58
|
+
|
|
59
|
+
@singleton
|
|
60
|
+
@provider
|
|
61
|
+
def provide_sqs(self) -> ISQSConnector:
|
|
62
|
+
from modmex_lambda.connectors.sqs import Connector
|
|
63
|
+
|
|
64
|
+
return Connector()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
__all__ = ["AwsConnectorsModule"]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from modmex_lambda.connectors.is3 import IS3Connector
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Connector(IS3Connector):
|
|
5
|
+
|
|
6
|
+
def __init__(self, bucket_name, client = None) -> None:
|
|
7
|
+
self.bucket_name = bucket_name
|
|
8
|
+
self._client = client
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def client(self):
|
|
12
|
+
if not self._client:
|
|
13
|
+
import boto3
|
|
14
|
+
self._client = boto3.client('s3')
|
|
15
|
+
return self._client
|
|
16
|
+
|
|
17
|
+
def put_object(self, input_params):
|
|
18
|
+
params = {
|
|
19
|
+
'Bucket': self.bucket_name,
|
|
20
|
+
**input_params
|
|
21
|
+
}
|
|
22
|
+
return self.client.put_object(**params)
|
|
23
|
+
|
|
24
|
+
def get_object(self, input_params):
|
|
25
|
+
params = {
|
|
26
|
+
'Bucket': self.bucket_name,
|
|
27
|
+
**input_params
|
|
28
|
+
}
|
|
29
|
+
return self.client.get_object(**params)
|
|
30
|
+
|
|
31
|
+
def list_objects(self, input_params):
|
|
32
|
+
params = {
|
|
33
|
+
'Bucket': self.bucket_name,
|
|
34
|
+
**input_params
|
|
35
|
+
}
|
|
36
|
+
return self.client.list_objects_v2(**params)
|
|
37
|
+
|
|
38
|
+
def delete_object(self, input_params):
|
|
39
|
+
params = {
|
|
40
|
+
'Bucket': self.bucket_name,
|
|
41
|
+
**input_params
|
|
42
|
+
}
|
|
43
|
+
return self.client.delete_object(**params)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from modmex_lambda.connectors.isns import ISNSConnector
|
|
4
|
+
from modmex_lambda.stream.utils.aws import get_region
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Connector(ISNSConnector):
|
|
8
|
+
def __init__(self, topic_arn = os.getenv('TOPIC_ARN'), client = None) -> None:
|
|
9
|
+
self.topic_arn = topic_arn
|
|
10
|
+
self._client = client
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def client(self):
|
|
14
|
+
if not self._client:
|
|
15
|
+
import boto3
|
|
16
|
+
self._client = boto3.client('sns', region_name=get_region(self.topic_arn))
|
|
17
|
+
return self._client
|
|
18
|
+
|
|
19
|
+
def publish(self, input_params):
|
|
20
|
+
params = {
|
|
21
|
+
'TopicArn': self.topic_arn,
|
|
22
|
+
**input_params
|
|
23
|
+
}
|
|
24
|
+
return self.client.publish(**params)
|
|
25
|
+
|
|
26
|
+
def publish_batch(self, input_params):
|
|
27
|
+
params = {
|
|
28
|
+
'TopicArn': self.topic_arn,
|
|
29
|
+
**input_params
|
|
30
|
+
}
|
|
31
|
+
return self.client.publish_batch(**params)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from modmex_lambda.connectors.isqs import ISQSConnector
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Connector(ISQSConnector):
|
|
6
|
+
|
|
7
|
+
def __init__(self, queue_url = os.getenv('QUEUE_URL'), client = None) -> None:
|
|
8
|
+
self.queue_url = queue_url
|
|
9
|
+
self._client = client
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def client(self):
|
|
13
|
+
if not self._client:
|
|
14
|
+
import boto3
|
|
15
|
+
self._client = boto3.client('sqs')
|
|
16
|
+
return self._client
|
|
17
|
+
|
|
18
|
+
def send_message(self, input_params):
|
|
19
|
+
params = {
|
|
20
|
+
'QueueUrl': self.queue_url,
|
|
21
|
+
**input_params
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return self.client.send_message(**params)
|
|
25
|
+
|
|
26
|
+
def send_message_batch(self, input_params):
|
|
27
|
+
params = {
|
|
28
|
+
'QueueUrl': self.queue_url,
|
|
29
|
+
**input_params
|
|
30
|
+
}
|
|
31
|
+
return self.client.send_message_batch(**params)
|