Adding policy manager and a1 sdnc vth
[it/otf.git] / a1-policy-manager-vth / app / helpers / response_helper.py
diff --git a/a1-policy-manager-vth/app/helpers/response_helper.py b/a1-policy-manager-vth/app/helpers/response_helper.py
new file mode 100644 (file)
index 0000000..2058347
--- /dev/null
@@ -0,0 +1,221 @@
+import ast\r
+import requests\r
+from configparser import ConfigParser\r
+import os\r
+import datetime\r
+import json\r
+from flask import request, jsonify, current_app\r
+from app.helpers.time_helper import unix_time_millis\r
+from app.errors.bad_request_exception import BadRequestException\r
+import requests\r
+\r
+"""\r
+    Module Info:\r
+"""\r
+def create_headers(enable_cache=True, content_type="application/json", connection="Keep-Alive"):\r
+    headers = {'Cache-Control':'no-cache, no-store, must-revalidate', "Pragma":"no-cache", "Expires":"0"} if not enable_cache else {}\r
+    headers['content-type'] = content_type\r
+    headers['connection'] = connection\r
+    return headers\r
+def create_url(config=None, uri_path = "/", url_string=None):\r
+    return config['api']['base_url'] +":"+ config['api']['port']+uri_path if url_string is None else url_string\r
+\r
+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
+    try:\r
+        string_to_dict = ast.literal_eval(string)\r
+    except(Exception):\r
+        raise BadRequestException(406, response_message)\r
+    return True\r
+def route_check(config=None, get_function=None, post_function=None, put_function=None, delete_function=None):\r
+    """\r
+     Info:\r
+        Since all routes do the same pre-check and have a similar skeleton, this function just refactored the pre-check for code reuse\r
+     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
+        get_function => type: function\r
+        put_function => type: function\r
+        delete_function => type: function\r
+    Returns:\r
+        returns the return of the function call, typically a jsonified response.\r
+        you can capture response in a var and execute logic or you can just return the function call/response \r
+    E.G.:\r
+        response = route_check(post_function = handle_post)\r
+        return route_check(get_function = handle_get, post_function = handle_post)\r
+    """\r
+    if not request.is_json: raise BadRequestException(406, "Invalid Json Request")\r
+\r
+\r
+    response_dict = vth_response_dic()\r
+    start_time = unix_time_millis(datetime.datetime.now())\r
+    status_code = 200\r
+    ret_url = request.args.get('retURL')\r
+\r
+    query = ""\r
+    json_body = ""\r
+    request_data = request.json\r
+    json_keys = set(request_data)\r
+    action_request = request_data.get("action").lower()\r
+    valid_actions = {"policies", "policy", "policy_ids", "policy_schema", "policy_schemas", "policy_status", "policy_types", "ric", "rics", "service", "services", "keepalive", "status" }\r
+    required_keys = {"action", "method", "auth", "action_data"}\r
+\r
+    #check for valid action and json request contains required keys\r
+    if not required_keys <= json_keys: raise BadRequestException(406, "Json request is missing required keys {}".format(required_keys))\r
+    if not action_request in valid_actions: raise BadRequestException(406, "Action is not supported {}".format(action_request))\r
+    #check request's action_data key contains required keys\r
+    if 'query' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody ")\r
+    if 'jsonBody' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody")\r
+\r
+    query = request.json['action_data']['query'] if 'query' in request.json['action_data'] else ""\r
+    json_body = request.json['action_data']['jsonBody'] if 'jsonBody' in request.json['action_data'] else ""\r
+\r
+\r
+    if valid_string_json(query) and valid_string_json(json_body):\r
+        if(request.method == 'GET'):\r
+            response_dict = get_function(request, response_dict, config)\r
+        elif(request.method == 'POST'):\r
+            response_dict = post_function(request, response_dict, config)\r
+        elif(request.method == 'PUT'):\r
+            response_dict = put_function(request, response_dict, config)\r
+        elif(request.method == 'DELETE'):\r
+            response_dict = delete_function(request, response_dict, config)\r
+    else:\r
+        raise BadRequestException(406, "Invalid JSON Strings")\r
+    end_time = unix_time_millis(datetime.datetime.now())\r
+    response_dict['vthResponse']['testDurationMS'] = end_time-start_time\r
+    if ret_url is not None:\r
+        sendCallback(ret_url,response_dict)\r
+        return '',200\r
+    return jsonify(response_dict), status_code\r
+\r
+def get_proxies(config):\r
+    proxy_enabled = config.getboolean('resource', 'proxy_enabled')\r
+    req_proxies = {\r
+        'http': None,\r
+        'https': None\r
+    }\r
+    if not proxy_enabled:\r
+        return None\r
+    else:\r
+        req_proxies['http'] = config['resource']['http_proxy']         \r
+        req_proxies['https'] = config['resource']['https_proxy']\r
+        return req_proxies\r
+def get_credentials(json_data, config):\r
+    auth_enabled = config.getboolean('auth', 'creds_enabled')\r
+    if not auth_enabled:\r
+        return None\r
+    else:\r
+        username = config['auth']['username'] if 'username' not in json_data['auth'] else json_data['auth']['username']\r
+        password = config['auth']['password'] if 'password' not in json_data['auth'] else json_data['auth']['password']\r
+        return (username, password)\r
+def vth_response_dic():\r
+    """\r
+    Args:\r
+    Returns:\r
+    Examples:\r
+    """\r
+    response_data = {\r
+        "vthResponse": {\r
+            "testDurationMS": "",\r
+            'dateTimeUTC': str(datetime.datetime.now()),\r
+            "abstractMessage": "Success",\r
+            "resultData": {}\r
+        }\r
+    }\r
+    return response_data\r
+\r
+def sendCallback(url, data):\r
+    try:\r
+        if type(data) is not dict:\r
+            data = {"msg": data}\r
+        current_app.logger.info("sending callback")\r
+        requests.post(url, json=data)\r
+    except Exception as e:\r
+        current_app.logger.info(e)\r
+    return\r
+\r
+def get_request_data(request):\r
+    if not request.is_json:\r
+        raise ValueError("request must be json")\r
+    requestData = request.get_json()\r
+    return requestData\r
+\r
+\r
+def valid_json(data):\r
+\r
+    try:\r
+        _ = json.loads(data)\r
+    except ValueError as e:\r
+        return False\r
+    return True\r
+def get_config(config_file_name):\r
+    config = ConfigParser(os.environ)\r
+    config.read(config_file_name)\r
+    return config\r
+\r
+def validate_request(request_data, isPublish=True):\r
+    return\r
+    missing_params = []\r
+\r
+    if 'topic_name' not in request_data:\r
+        missing_params.append("topic_name")\r
+    if isPublish:\r
+        if 'data' not in request_data:\r
+            missing_params.append('data')\r
+    else:\r
+        if 'consumer_group' not in request_data:\r
+            missing_params.append('consumer_group')\r
+        if 'consumer_id' not in request_data:\r
+            missing_params.append('consumer_id')\r
+\r
+    if missing_params:\r
+        err_msg = '{} request requires the following: '.format('publish' if isPublish else 'subscribe')\r
+        err_msg += ','.join(missing_params)\r
+        raise KeyError(err_msg)\r
+\r
+\r
+def build_url(config, request_data, is_publish=True):\r
+    if is_publish:\r
+        base_path = config['resource']['base_address'] + config['resource']['publish']\r
+        topic_name = request_data['topic_name']\r
+        publish_address = base_path.format(topic_name=topic_name)\r
+        return publish_address\r
+\r
+    base_path = config['resource']['base_address'] + config['resource']['subscribe']\r
+    topic_name = request_data['topic_name']\r
+    consumer_group = request_data['consumer_group']\r
+    consumer_id = request_data['consumer_id']\r
+    subscribe_address = base_path.format(topic_name=topic_name, consumer_group=consumer_group, consumer_id=consumer_id)\r
+    if ('timeout' in request_data):\r
+        subscribe_address = (subscribe_address + '?timeout={}').format(request_data['timeout'])\r
+    return subscribe_address\r
+\r
+\r
+def send_request(url, config, is_subscribe_request=False, payload=None):\r
+    # setup default values\r
+    auth_enabled = config.getboolean('auth', 'auth_enabled')\r
+    proxy_enabled = config.getboolean('resource', 'proxy_enabled')\r
+    username = ''\r
+    password = ''\r
+    req_proxies = {\r
+        'http': None,\r
+        'https': None\r
+    }\r
+    # place proxy and authentication information\r
+    if auth_enabled:\r
+        username = config['auth']['username']\r
+        password = config['auth']['password']\r
+    if proxy_enabled:\r
+        req_proxies['http'] = config['resource']['http_proxy']\r
+        req_proxies['https'] = config['resource']['https_proxy']\r
+\r
+    # for subscribe request\r
+    if is_subscribe_request:\r
+        return requests.get(url,\r
+                            auth=(username, password) if auth_enabled else None,\r
+                            proxies=req_proxies if proxy_enabled else None)\r
+    # for publish request\r
+    req_headers = {'Content-type': 'application/json'}\r
+    return requests.post(url,\r
+                         json=payload,\r
+                         auth=(username, password) if auth_enabled else None,\r
+                         proxies=req_proxies if proxy_enabled else None,\r
+                         headers=req_headers)\r