|
| 1 | +import base64 |
1 | 2 | import gzip
|
2 | 3 | import json
|
3 |
| -import base64 |
4 | 4 | import logging
|
5 |
| -from datetime import datetime |
6 | 5 | import re
|
| 6 | +from datetime import datetime |
7 | 7 | from typing import Any
|
| 8 | + |
8 | 9 | import boto3
|
9 | 10 |
|
10 | 11 | # Set up logging
|
11 | 12 | logger = logging.getLogger(__name__)
|
12 | 13 | logger.setLevel(logging.DEBUG)
|
13 | 14 |
|
14 |
| -ec2_resource = boto3.resource('ec2', region_name='us-west-2') |
15 |
| -table = boto3.resource('dynamodb', region_name='us-west-2').Table('XGBoostCIWorkerProvisionRecord') |
| 15 | +ec2_resource = boto3.resource("ec2", region_name="us-west-2") |
| 16 | +table = boto3.resource("dynamodb", region_name="us-west-2").Table( |
| 17 | + "XGBoostCIWorkerProvisionRecord" |
| 18 | +) |
| 19 | + |
16 | 20 |
|
17 | 21 | def get_os_of_ami(image_id: str) -> str:
|
18 | 22 | image = ec2_resource.Image(image_id)
|
19 | 23 | platform_details = image.platform_details
|
20 |
| - assert platform_details in ['Linux/UNIX', 'Windows'] |
21 |
| - if platform_details == 'Linux/UNIX': |
22 |
| - return 'Linux' |
| 24 | + assert platform_details in ["Linux/UNIX", "Windows"] |
| 25 | + if platform_details == "Linux/UNIX": |
| 26 | + return "Linux" |
23 | 27 | return platform_details
|
24 | 28 |
|
| 29 | + |
25 | 30 | def lambda_handler(event: Any, context: Any):
|
26 |
| - cw_data = event['awslogs']['data'] |
| 31 | + cw_data = event["awslogs"]["data"] |
27 | 32 | compressed_payload = base64.b64decode(cw_data)
|
28 | 33 | uncompressed_payload = gzip.decompress(compressed_payload)
|
29 | 34 | payload = json.loads(uncompressed_payload)
|
30 |
| - log_events = payload['logEvents'] |
| 35 | + log_events = payload["logEvents"] |
31 | 36 | for log_event in log_events:
|
32 |
| - message = json.loads(log_event['message']) |
33 |
| - if ('eventType' not in message): |
34 |
| - logger.debug(f'Message not well-formed: {message}') |
| 37 | + message = json.loads(log_event["message"]) |
| 38 | + if "eventType" not in message: |
| 39 | + logger.debug(f"Message not well-formed: {message}") |
35 | 40 | continue
|
36 |
| - if message['eventType'] != 'AwsApiCall': |
| 41 | + if message["eventType"] != "AwsApiCall": |
37 | 42 | # Skip events that are not API calls, such as Insights
|
38 | 43 | continue
|
39 |
| - if ('eventName' not in message) or ('eventTime' not in message): |
40 |
| - logger.debug(f'Message not well-formed: {message}') |
| 44 | + if ("eventName" not in message) or ("eventTime" not in message): |
| 45 | + logger.debug(f"Message not well-formed: {message}") |
41 | 46 | continue
|
42 |
| - event_name = message['eventName'] |
43 |
| - event_time = message['eventTime'] |
44 |
| - if event_name == 'RunInstances': |
45 |
| - if (('responseElements' not in message) |
46 |
| - or (not message['responseElements']) |
47 |
| - or ('instancesSet' not in message['responseElements']) |
48 |
| - or (not message['responseElements']['instancesSet']) |
49 |
| - or ('items' not in message['responseElements']['instancesSet'])): |
| 47 | + event_name = message["eventName"] |
| 48 | + event_time = message["eventTime"] |
| 49 | + if event_name == "RunInstances": |
| 50 | + if ( |
| 51 | + ("responseElements" not in message) |
| 52 | + or (not message["responseElements"]) |
| 53 | + or ("instancesSet" not in message["responseElements"]) |
| 54 | + or (not message["responseElements"]["instancesSet"]) |
| 55 | + or ("items" not in message["responseElements"]["instancesSet"]) |
| 56 | + ): |
50 | 57 | # RunInstance that did not succeed
|
51 | 58 | continue
|
52 |
| - for ordinal, ec2 in enumerate(message['responseElements']['instancesSet']['items']): |
53 |
| - ec2_id = ec2['instanceId'] |
54 |
| - ec2_type = ec2['instanceType'] |
55 |
| - ec2_os = get_os_of_ami(ec2['imageId']) |
56 |
| - logger.info(f'RunInstances, InstanceID = {ec2_id} @ {event_time}') |
57 |
| - table.put_item(Item={ |
58 |
| - 'Date': event_time.split(sep='T', maxsplit=1)[0], |
59 |
| - 'Timestamp-Ordinal': f'{event_time}#{ordinal}', |
60 |
| - 'EventName': 'RunInstances', |
61 |
| - 'InstanceID': ec2_id, |
62 |
| - 'InstanceType': ec2_type, |
63 |
| - 'InstanceOS': ec2_os}) |
64 |
| - elif event_name == 'TerminateInstances': |
65 |
| - if (('responseElements' not in message) |
66 |
| - or (not message['responseElements']) |
67 |
| - or ('instancesSet' not in message['responseElements']) |
68 |
| - or (not message['responseElements']['instancesSet']) |
69 |
| - or ('items' not in message['responseElements']['instancesSet'])): |
| 59 | + for ordinal, ec2 in enumerate( |
| 60 | + message["responseElements"]["instancesSet"]["items"] |
| 61 | + ): |
| 62 | + ec2_id = ec2["instanceId"] |
| 63 | + ec2_type = ec2["instanceType"] |
| 64 | + ec2_os = get_os_of_ami(ec2["imageId"]) |
| 65 | + logger.info(f"RunInstances, InstanceID = {ec2_id} @ {event_time}") |
| 66 | + table.put_item( |
| 67 | + Item={ |
| 68 | + "Date": event_time.split(sep="T", maxsplit=1)[0], |
| 69 | + "Timestamp-Ordinal": f"{event_time}#{ordinal}", |
| 70 | + "EventName": "RunInstances", |
| 71 | + "InstanceID": ec2_id, |
| 72 | + "InstanceType": ec2_type, |
| 73 | + "InstanceOS": ec2_os, |
| 74 | + } |
| 75 | + ) |
| 76 | + elif event_name == "TerminateInstances": |
| 77 | + if ( |
| 78 | + ("responseElements" not in message) |
| 79 | + or (not message["responseElements"]) |
| 80 | + or ("instancesSet" not in message["responseElements"]) |
| 81 | + or (not message["responseElements"]["instancesSet"]) |
| 82 | + or ("items" not in message["responseElements"]["instancesSet"]) |
| 83 | + ): |
70 | 84 | # TerminateInstances that did not succeed
|
71 | 85 | continue
|
72 |
| - for ordinal, ec2 in enumerate(message['responseElements']['instancesSet']['items']): |
73 |
| - ec2_id = ec2['instanceId'] |
74 |
| - logger.info(f'TerminateInstances, InstanceID = {ec2_id} @ {event_time}') |
75 |
| - table.put_item(Item={ |
76 |
| - 'Date': event_time.split(sep='T', maxsplit=1)[0], |
77 |
| - 'Timestamp-Ordinal': f'{event_time}#{ordinal}', |
78 |
| - 'EventName': 'TerminateInstances', |
79 |
| - 'InstanceID': ec2_id}) |
| 86 | + for ordinal, ec2 in enumerate( |
| 87 | + message["responseElements"]["instancesSet"]["items"] |
| 88 | + ): |
| 89 | + ec2_id = ec2["instanceId"] |
| 90 | + logger.info( |
| 91 | + f"TerminateInstances, InstanceID = {ec2_id} @ {event_time}" |
| 92 | + ) |
| 93 | + table.put_item( |
| 94 | + Item={ |
| 95 | + "Date": event_time.split(sep="T", maxsplit=1)[0], |
| 96 | + "Timestamp-Ordinal": f"{event_time}#{ordinal}", |
| 97 | + "EventName": "TerminateInstances", |
| 98 | + "InstanceID": ec2_id, |
| 99 | + } |
| 100 | + ) |
0 commit comments