205834786c093a019940375e437a66c925a022c3
[it/otf.git] / a1-policy-manager-vth / app / helpers / response_helper.py
1 import ast\r
2 import requests\r
3 from configparser import ConfigParser\r
4 import os\r
5 import datetime\r
6 import json\r
7 from flask import request, jsonify, current_app\r
8 from app.helpers.time_helper import unix_time_millis\r
9 from app.errors.bad_request_exception import BadRequestException\r
10 import requests\r
11 \r
12 """\r
13     Module Info:\r
14 """\r
15 def create_headers(enable_cache=True, content_type="application/json", connection="Keep-Alive"):\r
16     headers = {'Cache-Control':'no-cache, no-store, must-revalidate', "Pragma":"no-cache", "Expires":"0"} if not enable_cache else {}\r
17     headers['content-type'] = content_type\r
18     headers['connection'] = connection\r
19     return headers\r
20 def create_url(config=None, uri_path = "/", url_string=None):\r
21     return config['api']['base_url'] +":"+ config['api']['port']+uri_path if url_string is None else url_string\r
22 \r
23 def valid_string_json(string, response_message="Invalid json string in query or jsonBody, format requires quoted json object e.g. \"{'key':'value, key2:{'innerKey':'innerValue'}}\""):\r
24     try:\r
25         string_to_dict = ast.literal_eval(string)\r
26     except(Exception):\r
27         raise BadRequestException(406, response_message)\r
28     return True\r
29 def route_check(config=None, get_function=None, post_function=None, put_function=None, delete_function=None):\r
30     """\r
31      Info:\r
32         Since all routes do the same pre-check and have a similar skeleton, this function just refactored the pre-check for code reuse\r
33      Arguments (**kwargs): pass in the specified key(s) and  method(s) that handle the type of method, method must be allowed by route decorator\r
34         get_function => type: function\r
35         put_function => type: function\r
36         delete_function => type: function\r
37     Returns:\r
38         returns the return of the function call, typically a jsonified response.\r
39         you can capture response in a var and execute logic or you can just return the function call/response \r
40     E.G.:\r
41         response = route_check(post_function = handle_post)\r
42         return route_check(get_function = handle_get, post_function = handle_post)\r
43     """\r
44     if not request.is_json: raise BadRequestException(406, "Invalid Json Request")\r
45 \r
46 \r
47     response_dict = vth_response_dic()\r
48     start_time = unix_time_millis(datetime.datetime.now())\r
49     status_code = 200\r
50     ret_url = request.args.get('retURL')\r
51 \r
52     query = ""\r
53     json_body = ""\r
54     request_data = request.json\r
55     json_keys = set(request_data)\r
56     action_request = request_data.get("action").lower()\r
57     valid_actions = {"policies", "policy", "policy_ids", "policy_schema", "policy_schemas", "policy_status", "policy_types", "ric", "rics", "service", "services", "keepalive", "status" }\r
58     required_keys = {"action", "method", "auth", "action_data"}\r
59 \r
60     #check for valid action and json request contains required keys\r
61     if not required_keys <= json_keys: raise BadRequestException(406, "Json request is missing required keys {}".format(required_keys))\r
62     if not action_request in valid_actions: raise BadRequestException(406, "Action is not supported {}".format(action_request))\r
63     #check request's action_data key contains required keys\r
64     if 'query' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody ")\r
65     if 'jsonBody' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody")\r
66 \r
67     query = request.json['action_data']['query'] if 'query' in request.json['action_data'] else ""\r
68     json_body = request.json['action_data']['jsonBody'] if 'jsonBody' in request.json['action_data'] else ""\r
69 \r
70 \r
71     if valid_string_json(query) and valid_string_json(json_body):\r
72         if(request.method == 'GET'):\r
73             response_dict = get_function(request, response_dict, config)\r
74         elif(request.method == 'POST'):\r
75             response_dict = post_function(request, response_dict, config)\r
76         elif(request.method == 'PUT'):\r
77             response_dict = put_function(request, response_dict, config)\r
78         elif(request.method == 'DELETE'):\r
79             response_dict = delete_function(request, response_dict, config)\r
80     else:\r
81         raise BadRequestException(406, "Invalid JSON Strings")\r
82     end_time = unix_time_millis(datetime.datetime.now())\r
83     response_dict['vthResponse']['testDurationMS'] = end_time-start_time\r
84     if ret_url is not None:\r
85         sendCallback(ret_url,response_dict)\r
86         return '',200\r
87     return jsonify(response_dict), status_code\r
88 \r
89 def get_proxies(config):\r
90     proxy_enabled = config.getboolean('resource', 'proxy_enabled')\r
91     req_proxies = {\r
92         'http': None,\r
93         'https': None\r
94     }\r
95     if not proxy_enabled:\r
96         return None\r
97     else:\r
98         req_proxies['http'] = config['resource']['http_proxy']         \r
99         req_proxies['https'] = config['resource']['https_proxy']\r
100         return req_proxies\r
101 def get_credentials(json_data, config):\r
102     auth_enabled = config.getboolean('auth', 'creds_enabled')\r
103     if not auth_enabled:\r
104         return None\r
105     else:\r
106         username = config['auth']['username'] if 'username' not in json_data['auth'] else json_data['auth']['username']\r
107         password = config['auth']['password'] if 'password' not in json_data['auth'] else json_data['auth']['password']\r
108         return (username, password)\r
109 def vth_response_dic():\r
110     """\r
111     Args:\r
112     Returns:\r
113     Examples:\r
114     """\r
115     response_data = {\r
116         "vthResponse": {\r
117             "testDurationMS": "",\r
118             'dateTimeUTC': str(datetime.datetime.now()),\r
119             "abstractMessage": "Success",\r
120             "resultData": {}\r
121         }\r
122     }\r
123     return response_data\r
124 \r
125 def sendCallback(url, data):\r
126     try:\r
127         if type(data) is not dict:\r
128             data = {"msg": data}\r
129         current_app.logger.info("sending callback")\r
130         requests.post(url, json=data)\r
131     except Exception as e:\r
132         current_app.logger.info(e)\r
133     return\r
134 \r
135 def get_request_data(request):\r
136     if not request.is_json:\r
137         raise ValueError("request must be json")\r
138     requestData = request.get_json()\r
139     return requestData\r
140 \r
141 \r
142 def valid_json(data):\r
143 \r
144     try:\r
145         _ = json.loads(data)\r
146     except ValueError as e:\r
147         return False\r
148     return True\r
149 def get_config(config_file_name):\r
150     config = ConfigParser(os.environ)\r
151     config.read(config_file_name)\r
152     return config\r
153 \r
154 def validate_request(request_data, isPublish=True):\r
155     return\r
156     missing_params = []\r
157 \r
158     if 'topic_name' not in request_data:\r
159         missing_params.append("topic_name")\r
160     if isPublish:\r
161         if 'data' not in request_data:\r
162             missing_params.append('data')\r
163     else:\r
164         if 'consumer_group' not in request_data:\r
165             missing_params.append('consumer_group')\r
166         if 'consumer_id' not in request_data:\r
167             missing_params.append('consumer_id')\r
168 \r
169     if missing_params:\r
170         err_msg = '{} request requires the following: '.format('publish' if isPublish else 'subscribe')\r
171         err_msg += ','.join(missing_params)\r
172         raise KeyError(err_msg)\r
173 \r
174 \r
175 def build_url(config, request_data, is_publish=True):\r
176     if is_publish:\r
177         base_path = config['resource']['base_address'] + config['resource']['publish']\r
178         topic_name = request_data['topic_name']\r
179         publish_address = base_path.format(topic_name=topic_name)\r
180         return publish_address\r
181 \r
182     base_path = config['resource']['base_address'] + config['resource']['subscribe']\r
183     topic_name = request_data['topic_name']\r
184     consumer_group = request_data['consumer_group']\r
185     consumer_id = request_data['consumer_id']\r
186     subscribe_address = base_path.format(topic_name=topic_name, consumer_group=consumer_group, consumer_id=consumer_id)\r
187     if ('timeout' in request_data):\r
188         subscribe_address = (subscribe_address + '?timeout={}').format(request_data['timeout'])\r
189     return subscribe_address\r
190 \r
191 \r
192 def send_request(url, config, is_subscribe_request=False, payload=None):\r
193     # setup default values\r
194     auth_enabled = config.getboolean('auth', 'auth_enabled')\r
195     proxy_enabled = config.getboolean('resource', 'proxy_enabled')\r
196     username = ''\r
197     password = ''\r
198     req_proxies = {\r
199         'http': None,\r
200         'https': None\r
201     }\r
202     # place proxy and authentication information\r
203     if auth_enabled:\r
204         username = config['auth']['username']\r
205         password = config['auth']['password']\r
206     if proxy_enabled:\r
207         req_proxies['http'] = config['resource']['http_proxy']\r
208         req_proxies['https'] = config['resource']['https_proxy']\r
209 \r
210     # for subscribe request\r
211     if is_subscribe_request:\r
212         return requests.get(url,\r
213                             auth=(username, password) if auth_enabled else None,\r
214                             proxies=req_proxies if proxy_enabled else None)\r
215     # for publish request\r
216     req_headers = {'Content-type': 'application/json'}\r
217     return requests.post(url,\r
218                          json=payload,\r
219                          auth=(username, password) if auth_enabled else None,\r
220                          proxies=req_proxies if proxy_enabled else None,\r
221                          headers=req_headers)\r