-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
152 lines (104 loc) · 4.06 KB
/
Copy pathapp.py
File metadata and controls
152 lines (104 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import json
import logging
import os
import boto3
LOGGER = logging.getLogger()
RDS_DDL_QUEUE_URL_ENV_VAR = "RDS_DDL_QUEUE_URL"
class MalformedEvent(Exception):
"""Raised if a malformed event received"""
class MissingEnvironmentVariable(Exception):
"""Raised if a required environment variable is missing"""
def _silence_noisy_loggers():
"""Silence chatty libraries for better logging"""
for logger in ['boto3', 'botocore',
'botocore.vendored.requests.packages.urllib3']:
logging.getLogger(logger).setLevel(logging.WARNING)
def _configure_logger():
"""Configure python logger"""
level = logging.INFO
verbose = os.environ.get("VERBOSE", "")
if verbose.lower() == "true":
print("Will set the logging output to DEBUG")
level = logging.DEBUG
if len(logging.getLogger().handlers) > 0:
# The Lambda environment pre-configures a handler logging to stderr.
# If a handler is already configured, `.basicConfig` does not execute.
# Thus we set the level directly.
logging.getLogger().setLevel(level)
else:
logging.basicConfig(level=level)
def _check_missing_field(validation_dict, extraction_key):
"""Check if a field exists in a dictionary
:param validation_dict: Dictionary
:param extraction_key: String
:raises: MalformedEvent
"""
extracted_value = validation_dict.get(extraction_key)
if not extracted_value:
LOGGER.error(f"Missing '{extraction_key}' field in the event")
raise MalformedEvent
def _validate_field(validation_dict, extraction_key, expected_value):
"""Validate the passed in field
:param validation_dict: Dictionary
:param extraction_key: String
:param expected_value: String
:raises: ValueError
"""
extracted_value = validation_dict.get(extraction_key)
_check_missing_field(validation_dict, extraction_key)
if extracted_value != expected_value:
LOGGER.error(f"Incorrect value found for '{extraction_key}' field")
raise ValueError
def _extract_valid_event(event):
"""Validate incoming event and extract necessary attributes
:param event: Dictionary
:raises: MalformedEvent
:raises: ValueError
:rtype: Dictionary
"""
valid_event = {}
_validate_field(event, "source", "aws.rds")
_check_missing_field(event, "detail")
event_detail = event["detail"]
_validate_field(event_detail, "eventName", "CreateDBCluster")
_check_missing_field(event_detail, "responseElements")
return event_detail["responseElements"]
def _send_message_to_sqs(client, queue_url, message_dict):
"""Send message to SQS Queue
:param client: Boto3 client object (SQS)
:param queue_url: String
:param message_dict: Dictionary
:raises: Exception
"""
LOGGER.info(f"Attempting to send message to: {queue_url}")
resp = client.send_message(
QueueUrl=queue_url,
MessageBody=json.dumps(message_dict)
)
_check_missing_field(resp, "ResponseMetadata")
resp_metadata = resp["ResponseMetadata"]
_check_missing_field(resp_metadata, "HTTPStatusCode")
status_code = resp_metadata["HTTPStatusCode"]
if status_code == 200:
LOGGER.info("Successfully pushed message")
else:
raise Exception("Unable to push message")
def lambda_handler(event, context):
"""What executes when the program is run"""
# configure python logger
_configure_logger()
# silence chatty libraries
_silence_noisy_loggers()
valid_event = _extract_valid_event(event)
LOGGER.info("Extracted data to send to SQS")
sqs_client = boto3.client("sqs")
rds_ddl_queue_url = os.environ.get(RDS_DDL_QUEUE_URL_ENV_VAR)
if not rds_ddl_queue_url:
raise MissingEnvironmentVariable(
f"{RDS_DDL_QUEUE_URL_ENV_VAR} environment variable is required")
# send message to DDL Triggering Queue
_send_message_to_sqs(
sqs_client,
rds_ddl_queue_url,
valid_event)
sqs_client.close()