From 6df42283717121997ea36d6d7463cd76fcc2c165 Mon Sep 17 00:00:00 2001 From: David Mendez Date: Wed, 12 Aug 2020 12:10:26 -0500 Subject: [PATCH] Add blueprint for sagger description --- app/__init__.py | 44 +++++++++ app/{blueprint => blueprints}/__init__.py | 0 .../subset_generator_blueprint/__init__.py | 0 .../controllers/__init__.py | 0 .../subset_generator_controller.py | 0 .../swagger_description/__init__.py | 0 .../swagger_description_blueprint.py | 26 +++++ app/config.py | 97 +++++++++++++++++++ .../swagger.yml => app/swagger/swagger.yaml | 10 +- requirements.txt | 1 + 10 files changed, 172 insertions(+), 6 deletions(-) rename app/{blueprint => blueprints}/__init__.py (100%) rename app/{blueprint => blueprints}/subset_generator_blueprint/__init__.py (100%) rename app/{blueprint => blueprints}/subset_generator_blueprint/controllers/__init__.py (100%) rename app/{blueprint => blueprints}/subset_generator_blueprint/controllers/subset_generator_controller.py (100%) create mode 100644 app/blueprints/swagger_description/__init__.py create mode 100644 app/blueprints/swagger_description/swagger_description_blueprint.py create mode 100644 app/config.py rename swagger/swagger.yml => app/swagger/swagger.yaml (86%) diff --git a/app/__init__.py b/app/__init__.py index e69de29..3362f08 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -0,0 +1,44 @@ +""" +Entry file for the elasticsearch proxy app +""" + +from flask import Flask +from flask_cors import CORS + +from app.config import RUN_CONFIG +# from app.cache import CACHE +from app.blueprints.swagger_description.swagger_description_blueprint import SWAGGER_BLUEPRINT + + +def create_app(): + """ + Creates the flask app + :return: Elasticsearch proxy flask app + """ + base_path = RUN_CONFIG.get('base_path') + flask_app = Flask(__name__) + + enable_cors = RUN_CONFIG.get('enable_cors', False) + + if enable_cors: + CORS(flask_app) + + + # with flask_app.app_context(): + # CACHE.init_app(flask_app) + + # # pylint: disable=protected-access + # if RUN_CONFIG.get('cache_config').get('CACHE_TYPE') == 'memcached': + # CACHE.cache._client.behaviors['tcp_nodelay'] = True + # CACHE.cache._client.behaviors['_noreply'] = True + # CACHE.cache._client.behaviors['no_block'] = True + # CACHE.cache._client.behaviors['remove_failed'] = 10 + # CACHE.cache._client.behaviors['retry_timeout'] = 10 + # CACHE.cache._client.behaviors['retry_timeout'] = 600 + + flask_app.register_blueprint(SWAGGER_BLUEPRINT, url_prefix=f'{base_path}/swagger') + return flask_app + + +if __name__ == '__main__': + FLASK_APP = create_app() diff --git a/app/blueprint/__init__.py b/app/blueprints/__init__.py similarity index 100% rename from app/blueprint/__init__.py rename to app/blueprints/__init__.py diff --git a/app/blueprint/subset_generator_blueprint/__init__.py b/app/blueprints/subset_generator_blueprint/__init__.py similarity index 100% rename from app/blueprint/subset_generator_blueprint/__init__.py rename to app/blueprints/subset_generator_blueprint/__init__.py diff --git a/app/blueprint/subset_generator_blueprint/controllers/__init__.py b/app/blueprints/subset_generator_blueprint/controllers/__init__.py similarity index 100% rename from app/blueprint/subset_generator_blueprint/controllers/__init__.py rename to app/blueprints/subset_generator_blueprint/controllers/__init__.py diff --git a/app/blueprint/subset_generator_blueprint/controllers/subset_generator_controller.py b/app/blueprints/subset_generator_blueprint/controllers/subset_generator_controller.py similarity index 100% rename from app/blueprint/subset_generator_blueprint/controllers/subset_generator_controller.py rename to app/blueprints/subset_generator_blueprint/controllers/subset_generator_controller.py diff --git a/app/blueprints/swagger_description/__init__.py b/app/blueprints/swagger_description/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/blueprints/swagger_description/swagger_description_blueprint.py b/app/blueprints/swagger_description/swagger_description_blueprint.py new file mode 100644 index 0000000..a8f84dd --- /dev/null +++ b/app/blueprints/swagger_description/swagger_description_blueprint.py @@ -0,0 +1,26 @@ +""" +Blueprint in charge of sending the swagger configuration in json format. +""" +from pathlib import Path + +from flask import Blueprint, jsonify +import yaml + +from app.config import RUN_CONFIG + +SWAGGER_BLUEPRINT = Blueprint('swagger', __name__) + + +@SWAGGER_BLUEPRINT.route('/swagger.json') +def get_json(): + """ + :return: Responds to the request with the json version of the swagger description + """ + + yaml_file_path = Path(Path().absolute()).joinpath('app', 'swagger', 'swagger.yaml') + + with open(yaml_file_path, 'r') as stream: + swagger_desc = yaml.safe_load(stream) + swagger_desc['host'] = RUN_CONFIG.get('server_public_host') + swagger_desc['basePath'] = RUN_CONFIG.get('base_path') + return jsonify(swagger_desc) diff --git a/app/config.py b/app/config.py new file mode 100644 index 0000000..de8e773 --- /dev/null +++ b/app/config.py @@ -0,0 +1,97 @@ +""" + Module that handles the configuration of the app +""" +import os +from pathlib import Path +import hashlib +from enum import Enum +import yaml + +CUSTOM_CONFIG_FILE_PATH = os.getenv('CONFIG_FILE_PATH') +if CUSTOM_CONFIG_FILE_PATH is not None: + CONFIG_FILE_PATH = CUSTOM_CONFIG_FILE_PATH +else: + CONFIG_FILE_PATH = str(Path().absolute()) + '/config.yml' + +print('------------------------------------------------------------------------------------------------') +print('CONFIG_FILE_PATH: ', CONFIG_FILE_PATH) +print('------------------------------------------------------------------------------------------------') + + +class ImproperlyConfiguredError(Exception): + """Base class for exceptions in this module.""" + + +class RunEnvs(Enum): + """ + Class that defines the possible run environments + """ + DEV = 'DEV' + TEST = 'TEST' + STAGING = 'STAGING' + PROD = 'PROD' + + def __repr__(self): + return self.name + + def __str__(self): + return self.name + + +def hash_secret(secret): + """ + Returns a a digest of a secret you want to store in memory + :param secret: secret you want to hash + :return: a sha256 hash of the secret, encoded in hexadecimal + """ + + hashed = hashlib.sha256(secret.encode('UTF-8')).hexdigest() + return hashed + + +def verify_secret(prop_name, value): + """ + Verifies that a value in the current config (hashed) corresponds to the value passed as parameter (unhashed) + :param prop_name: name of the property in the configuration + :param value: clear text value of the property. + :return: True if the value is correct, false otherwise + """ + + hashed = hashlib.sha256(value.encode('UTF-8')).hexdigest() + has_must_be = RUN_CONFIG.get(prop_name) + + return hashed == has_must_be + + +print('Loading run config') +try: + RUN_CONFIG = yaml.load(open(CONFIG_FILE_PATH, 'r'), Loader=yaml.FullLoader) + print('Run config loaded') +except FileNotFoundError: + print('Config file not found. Attempting to load config from environment variable DELAYED_JOBS_RAW_CONFIG') + RAW_CONFIG = os.getenv('DELAYED_JOBS_RAW_CONFIG') + print('raw_config: ', RAW_CONFIG) + RUN_CONFIG = yaml.load(RAW_CONFIG, Loader=yaml.FullLoader) + +# Load defaults +ES_CONFIG = RUN_CONFIG.get('elasticsearch', {}) +DEFAULT_ES_CONFIG = { + 'host': 'https://www.ebi.ac.uk/chembl/glados-es' + +} +RUN_CONFIG['elasticsearch'] = { + **DEFAULT_ES_CONFIG, + **ES_CONFIG, +} + +CACHE_CONFIG = RUN_CONFIG.get('cache_config', {}) +DEFAULT_CACHE_CONFIG = { + 'CACHE_TYPE': 'simple' +} +RUN_CONFIG['cache_config'] = { + **DEFAULT_CACHE_CONFIG, + **CACHE_CONFIG, +} + +if RUN_CONFIG.get('base_path') is None: + RUN_CONFIG['base_path'] = '' diff --git a/swagger/swagger.yml b/app/swagger/swagger.yaml similarity index 86% rename from swagger/swagger.yml rename to app/swagger/swagger.yaml index b6221d2..2b7e1c3 100644 --- a/swagger/swagger.yml +++ b/app/swagger/swagger.yaml @@ -18,12 +18,12 @@ schemes: - "https" - "http" paths: - /es_subsets/generate_subset_index_from_ids: + /es_subsets/submit_subset_creation_from_ids: post: tags: - 'ES subsets' summary: 'Generates a subset index in elasticsearch' - description: 'Receives a list of ChEMBL IDs and generates a subset with the items that correspond to + description: 'Receives a list of ChEMBL IDs and starts to generate a subset with the items that correspond to the ids in the original index' operationId: 'generate_subset_index' produces: @@ -50,7 +50,5 @@ definitions: SubsetOperationResponse: type: 'object' properties: - subset_created: - type: 'object' - metadata: - type: 'object' \ No newline at end of file + task_id: + type: 'string' \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c5a91b4..238b3da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ pyyaml==5.1.2 elasticsearch>=7.0.0,<8.0.0 # Recommended by the official documentation gunicorn==20.0.4 marshmallow==3.5.0 +flask-cors==3.0.8 \ No newline at end of file -- GitLab