-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
146 lines (127 loc) · 4.36 KB
/
main.py
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
#!/usr/bin/env python3
import json
import sys
import requests
from datetime import date
from dateutil import parser
import config
def to_datetime(dt):
return parser.parse(dt)
class GCPStatusToSlack():
'''
Fetch GCP Status json and compare the last update of watched services incidents
to notify new events in a Slack channel
'''
def __init__(self):
r = requests.get(config.GCP_INCIDENTS_URL)
r.raise_for_status()
self.data = r.json()
self.delta = None
self.today = date.today()
def get_last_run(self):
'''
Get last state of delta file
'''
try:
fd = open(config.LAST_RUN_FILE, 'r')
content = fd.read()
fd.close()
self.delta = json.loads(content)
except Exception as e:
sys.stderr.write('Cannot read/parse delta file : {}. Using an empty'
'delta\n'.format(e))
self.delta = {}
def set_last_run(self):
'''
Write the delta state in file
'''
fd = open(config.LAST_RUN_FILE, 'w')
fd.write(
json.dumps(self.delta)
)
fd.close()
def cleanup(self):
'''
Delete old entries of the delta dict
'''
to_delete = [event for event, last_modified in self.delta.items() if \
to_datetime(last_modified).date() < self.today]
for key in to_delete:
del self.delta[key]
def emoji(self, event):
'''
Return an emoji depending of the severity
'''
return config.SEVERITY_EMOJIS.get(event['severity'], '')
def find_new_events(self):
'''
Find new events in the json
Filters events by keeping only watched services
'''
# let's keep only events who got modified today
filtered_events = [x for x in self.data if x['service_key'] in \
config.GCP_SERVICES and \
to_datetime(x['modified']).date() == self.today]
# then let's notify events that we don't know yet or events which got
# modified
for event in filtered_events:
event_id = str(event['number'])
if event_id not in self.delta or \
self.delta[event_id] < event['modified']:
self.notify(event)
def notify(self, event):
'''
Send notification to slack
'''
event_id = str(event['number'])
# if we recorded an event, let's find updates that are newer than the
# last run datetime
if event_id in self.delta:
updates = [
x for x in event['updates'] if \
to_datetime(x['modified']) > to_datetime(self.delta[event_id])
]
# if it's an event we don't know yet, notify every updates of today
else:
updates = [
x for x in event['updates'] if \
to_datetime(x['modified']).date() == self.today
]
# sort updates by creation date
updates = sorted(updates, key=lambda k: k['modified'])
# Save the last evend in the delta file
self.delta[event_id] = event['modified']
# notify every channels
for channel in config.SLACK_CHANNELS:
for update in updates:
notification = u'{}{} incident #{} update: {}\n'\
'More information: {}{}'.format(
self.emoji(event),
event['service_name'],
event['number'],
update['text'],
config.GCP_STATUS_URL,
event['uri'])
payload = {
'payload': json.dumps({
'channel': channel,
'username': config.SLACK_USERNAME,
'text': notification,
'icon_emoji': ':google:'
})
}
r = requests.post(
config.SLACK_HOOKS_SERVICE,
data=payload,
)
def run(self):
'''
Run routine
'''
self.get_last_run()
self.cleanup()
self.find_new_events()
self.set_last_run()
if __name__ == '__main__':
a = GCPStatusToSlack()
a.run()