blob: 9a5da5db159371b941f23ab49ef9de9397a58d66 [file] [log] [blame]
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +01001import json
2from logging.config import dictConfig
Michal Kobusfc1e7732019-05-16 18:30:48 +02003import time
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +01004
5from flask import Flask, Response, jsonify, request
Michal Kobusafbf4d02018-11-28 14:18:05 +01006from prometheus_client import make_wsgi_app
Michal Kobus4104c102019-02-22 17:05:11 +01007from requests.exceptions import ConnectionError as RequestsConnectionError
8
Michal Kobusfc1e7732019-05-16 18:30:48 +02009from simple_salesforce.exceptions import SalesforceError
10from simple_settings import settings
11from werkzeug.wsgi import DispatcherMiddleware
12from uwsgidecorators import mulefunc
13
Michal Kobus211ee922019-04-15 17:44:06 +020014from sf_notifier.helpers import alert_fields_and_action, create_file
15from sf_notifier.salesforce.client import SESSION_FILE, SalesforceClient
Michal Kobusfc1e7732019-05-16 18:30:48 +020016from sf_notifier.salesforce.settings import CASE_STATUS
Michal Kobusafbf4d02018-11-28 14:18:05 +010017
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +010018
19dictConfig(settings.LOGGING)
20
Michal Kobusafbf4d02018-11-28 14:18:05 +010021app = Flask(__name__)
22app_dispatch = DispatcherMiddleware(app, {
23 '/metrics': make_wsgi_app()
24})
25
Michal Kobus211ee922019-04-15 17:44:06 +020026
27create_file(SESSION_FILE)
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +010028sf_cli = SalesforceClient(settings.SF_CONFIG)
29
30
Michal Kobus819cf022018-11-29 16:39:22 +010031@app.route('/info', methods=['GET'])
32def info():
Michal Kobus73d33522018-12-10 11:41:13 +010033 return jsonify({
34 'version': settings.VERSION,
35 'hashing': sf_cli.hash_func.__name__
36 })
Michal Kobus819cf022018-11-29 16:39:22 +010037
38
Michal Kobusfc1e7732019-05-16 18:30:48 +020039@mulefunc
40def offload(action, fields):
41 try:
42 getattr(sf_cli, action)(*fields)
43 except (SalesforceError, RequestsConnectionError) as err:
44 msg = 'Salesforce request failure: {}.'.format(err)
45 sf_cli.metrics['sf_error_count'].inc()
46 app.logger.error(msg)
47
48
49def create_case_results(alert_ids):
50 cases = {}
51 is_error = False
52
53 while len(alert_ids) > len(cases):
54 for alert_id in alert_ids:
55 case = sf_cli._registered_alerts.get(alert_id)
56
57 if case is None:
58 continue
59
60 if case['id'] not in CASE_STATUS:
61 cases[alert_id] = {}
62 cases[alert_id]['case'] = case['id']
63 if case['id'] == 'error':
64 if sf_cli._feed_update_ready(case['last_update']):
65 continue
66 is_error = True
67 cases[alert_id] = {}
68 cases[alert_id]['error'] = case['error']
69
70 time.sleep(0.2)
71 return cases, is_error
72
73
74def close_case_results(alert_ids):
75 # timeout is implicit error
76 cases = {}
77
78 while len(alert_ids) > 0:
79 for alert_id in alert_ids:
80 case = sf_cli._registered_alerts.get(alert_id)
81
82 if case is None:
83 cases[alert_id] = {'status': 'closed'}
84 alert_ids.pop(alert_ids.index(alert_id))
85 time.sleep(0.2)
86 return cases, False
87
88
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +010089@app.route('/hook', methods=['POST'])
90def webhook_receiver():
91
92 try:
93 data = json.loads(request.data)
94 except ValueError:
Michal Kobus17726ae2018-11-27 12:59:55 +010095 msg = 'Invalid request data: {}.'.format(request.data)
96 app.logger.error(msg)
97 return Response(json.dumps({'error': msg}),
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +010098 status=400,
99 mimetype='application/json')
100
101 app.logger.info('Received requests: {}'.format(data))
102
Michal Kobusfc1e7732019-05-16 18:30:48 +0200103 alert_ids = []
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +0100104 for alert in data['alerts']:
Michal Kobusfc1e7732019-05-16 18:30:48 +0200105 alert['labels']['env_id'] = sf_cli.environment
106 alert_ids.append(sf_cli.get_alert_id(alert['labels']))
107 fields, action = alert_fields_and_action(alert)
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +0100108
Michal Kobusfc1e7732019-05-16 18:30:48 +0200109 offload(action, fields)
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +0100110
Michal Kobusfc1e7732019-05-16 18:30:48 +0200111 cases, is_error = globals()[action + '_results'](alert_ids)
112
113 if is_error:
114 return Response(json.dumps(cases),
115 status=500,
116 mimetype='application/json')
117
Mateusz Matuszkowiak2820c662018-11-21 12:07:25 +0100118 return jsonify(cases)
119
120
121if __name__ == '__main__':
122 app.run()