Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit 32b4b89

Browse files
authored
Merge pull request #5 from hypoport/dev
implements basic support for Cloudwatch-Events
2 parents dfb1e08 + 3ec1e8c commit 32b4b89

File tree

4 files changed

+152
-4
lines changed

4 files changed

+152
-4
lines changed

aws_dataclasses/base.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,30 @@
55
from dataclasses import dataclass
66

77

8-
def _handle_nonexisting_fields(item: Dict, cls):
8+
def _check_fields(item: Dict, cls):
99
out = {}
1010
for k, v in item.items():
11-
if k not in cls.__dataclass_fields__:
11+
normalized_key = _normalize_key(k)
12+
if normalized_key not in cls.__dataclass_fields__:
1213
warnings.warn(f"Found field \"{k}\" in input, which is not part of dataclass \"{cls.__name__}\"",
1314
RuntimeWarning)
1415
else:
15-
out[k] = v
16+
out[normalized_key] = v
1617
return out
1718

1819

20+
def _normalize_key(identifier: str):
21+
res = identifier.replace("-", "_")
22+
return res
23+
24+
1925
@dataclass
2026
class GenericDataClass:
2127
@classmethod
2228
def from_json(cls, input: Union[str, Dict]):
2329
if isinstance(input, str):
2430
input = json.loads(input)
25-
input = _handle_nonexisting_fields(input, cls)
31+
input = _check_fields(input, cls)
2632
return cls(**input)
2733

2834

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from datetime import datetime
2+
from typing import Dict, List, Any
3+
4+
import arrow
5+
from dataclasses import dataclass
6+
7+
from aws_dataclasses.base import EventClass
8+
9+
10+
@dataclass
11+
class CloudWatchEvent(EventClass):
12+
version: str
13+
id: str
14+
detail_type: str
15+
source: str
16+
account: str
17+
time: datetime
18+
region: str
19+
resources: List[str]
20+
detail: Dict[str, Any]
21+
22+
def __post_init__(self):
23+
self.time = arrow.get(self.time).datetime
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"version": "0",
3+
"id": "9abea4c9-79cd-f4e9-4826-e2bd59590b5c",
4+
"detail-type": "Batch Job State Change",
5+
"source": "aws.batch",
6+
"account": "1234567890",
7+
"time": "2018-09-05T04:09:49Z",
8+
"region": "eu-central-1",
9+
"resources": [
10+
"arn:aws:batch:eu-central-1:1234567890:job/6882ce8d-359c-427b-834f-331158e5d093"
11+
],
12+
"detail": {
13+
"jobName": "TestJob",
14+
"jobId": "6882ce8d-359c-427b-834f-331158e5d093",
15+
"jobQueue": "arn:aws:batch:eu-central-1:1234567890:job-queue/LowPriority",
16+
"status": "FAILED",
17+
"attempts": [
18+
{
19+
"container": {
20+
"containerInstanceArn": "arn:aws:ecs:eu-central-1:1234567890:container-instance/2a7a92e1-2366-45bb-b7b3-13744dc3600e",
21+
"taskArn": "arn:aws:ecs:eu-central-1:1234567890:task/e6cba8d9-953d-4398-b31f-79fc8917f690",
22+
"exitCode": 1,
23+
"logStreamName": "TestJob/default/e6cba8d9-953d-4398-b31f-79fc8917f690"
24+
},
25+
"startedAt": 1536120182446,
26+
"stoppedAt": 1536120313655,
27+
"statusReason": "Essential container in task exited"
28+
},
29+
{
30+
"container": {
31+
"containerInstanceArn": "arn:aws:ecs:eu-central-1:1234567890:container-instance/2a7a92e1-2366-45bb-b7b3-13744dc3600e",
32+
"taskArn": "arn:aws:ecs:eu-central-1:1234567890:task/daf877c1-a477-468c-bafd-7ee1dc87c602",
33+
"exitCode": 1,
34+
"logStreamName": "TestJob/default/daf877c1-a477-468c-bafd-7ee1dc87c602"
35+
},
36+
"startedAt": 1536120320516,
37+
"stoppedAt": 1536120452900,
38+
"statusReason": "Essential container in task exited"
39+
},
40+
{
41+
"container": {
42+
"containerInstanceArn": "arn:aws:ecs:eu-central-1:1234567890:container-instance/2a7a92e1-2366-45bb-b7b3-13744dc3600e",
43+
"taskArn": "arn:aws:ecs:eu-central-1:1234567890:task/c44c626d-2667-4880-84c9-a397a7f9e785",
44+
"exitCode": 1,
45+
"logStreamName": "TestJob/default/c44c626d-2667-4880-84c9-a397a7f9e785"
46+
},
47+
"startedAt": 1536120457126,
48+
"stoppedAt": 1536120588113,
49+
"statusReason": "Essential container in task exited"
50+
}
51+
],
52+
"statusReason": "Essential container in task exited",
53+
"createdAt": 1536120031010,
54+
"retryStrategy": {
55+
"attempts": 3
56+
},
57+
"startedAt": 1536120457126,
58+
"stoppedAt": 1536120588113,
59+
"dependsOn": [],
60+
"jobDefinition": "arn:aws:batch:eu-central-1:1234567890:job-definition/TestJob:2",
61+
"parameters": {},
62+
"container": {
63+
"image": "1234567890.dkr.ecr.eu-central-1.amazonaws.com/testjob:latest",
64+
"vcpus": 2,
65+
"memory": 256,
66+
"command": [
67+
"python",
68+
"-m",
69+
"redshift_anonymizer.main"
70+
],
71+
"jobRoleArn": "arn:aws:iam::1234567890:role/service/RedshiftAnonymizerJob-BatchJob-dev",
72+
"volumes": [],
73+
"environment": [
74+
{
75+
"name": "STAGE",
76+
"value": "dev"
77+
}
78+
],
79+
"mountPoints": [],
80+
"readonlyRootFilesystem": true,
81+
"ulimits": [],
82+
"privileged": false,
83+
"exitCode": 1,
84+
"containerInstanceArn": "arn:aws:ecs:eu-central-1:1234567890:container-instance/2a7a92e1-2366-45bb-b7b3-13744dc3600e",
85+
"taskArn": "arn:aws:ecs:eu-central-1:1234567890:task/c44c626d-2667-4880-84c9-a397a7f9e785",
86+
"logStreamName": "TestJob/default/c44c626d-2667-4880-84c9-a397a7f9e785"
87+
}
88+
}
89+
}

tests/test_cloudwatch_event.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import datetime
2+
3+
import pytest
4+
from dateutil.tz import tzutc
5+
6+
from aws_dataclasses.cloudwatch_event import CloudWatchEvent
7+
8+
from .util import get_event_dict
9+
10+
11+
@pytest.fixture(scope="module")
12+
def cloudwatch_event_raw():
13+
return get_event_dict("cloudwatch_event.json")
14+
15+
16+
@pytest.fixture(scope="module")
17+
def cloudwatch_event(cloudwatch_event_raw):
18+
return CloudWatchEvent.from_event(cloudwatch_event_raw)
19+
20+
21+
def test_toplevel_items(cloudwatch_event):
22+
evt = cloudwatch_event
23+
assert evt.version == "0"
24+
assert evt.id == "9abea4c9-79cd-f4e9-4826-e2bd59590b5c"
25+
assert evt.detail_type == "Batch Job State Change"
26+
assert evt.source == "aws.batch"
27+
assert evt.time == datetime.datetime(2018, 9, 5, 4, 9, 49, tzinfo=tzutc())
28+
assert evt.region == "eu-central-1"
29+
assert evt.account == "1234567890"
30+
assert evt.resources == ["arn:aws:batch:eu-central-1:1234567890:job/6882ce8d-359c-427b-834f-331158e5d093"]

0 commit comments

Comments
 (0)