diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-10-25 14:53:54 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-10-25 14:53:54 +0200 |
| commit | aa9b32f8cd1467e9718959f400f6777e5d71737d (patch) | |
| tree | b88bbede15108c6855d7f94ded4c7054df186a72 /opendc-web/opendc-web-api/app.py | |
| parent | eb0e0a3bc557c05a70eead388797ab850ea87366 (diff) | |
| parent | b7a71e5b4aa77b41ef41deec2ace42b67a5a13a7 (diff) | |
merge: Integrate v2.1 progress into public repository
This pull request integrates the changes planned for the v2.1 release of
OpenDC into the public Github repository in order to sync the progress
of both repositories.
Diffstat (limited to 'opendc-web/opendc-web-api/app.py')
| -rwxr-xr-x | opendc-web/opendc-web-api/app.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/opendc-web/opendc-web-api/app.py b/opendc-web/opendc-web-api/app.py new file mode 100755 index 00000000..36c80b7a --- /dev/null +++ b/opendc-web/opendc-web-api/app.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +import mimetypes +import os + +from dotenv import load_dotenv +from flask import Flask, jsonify, redirect +from flask_compress import Compress +from flask_cors import CORS +from flask_restful import Api +from flask_swagger_ui import get_swaggerui_blueprint +from marshmallow import ValidationError + +from opendc.api.jobs import JobList, Job +from opendc.api.portfolios import Portfolio, PortfolioScenarios +from opendc.api.prefabs import Prefab, PrefabList +from opendc.api.projects import ProjectList, Project, ProjectTopologies, ProjectPortfolios +from opendc.api.scenarios import Scenario +from opendc.api.schedulers import SchedulerList +from opendc.api.topologies import Topology +from opendc.api.traces import TraceList, Trace +from opendc.auth import AuthError +from opendc.util import JSONEncoder + + +# Load environmental variables from dotenv file +load_dotenv() + + +def setup_sentry(): + """ + Setup the Sentry integration for Flask if a DSN is supplied via the environmental variables. + """ + if 'SENTRY_DSN' not in os.environ: + return + + import sentry_sdk + from sentry_sdk.integrations.flask import FlaskIntegration + + sentry_sdk.init( + integrations=[FlaskIntegration()], + traces_sample_rate=0.1 + ) + + +def setup_api(app): + """ + Setup the API interface. + """ + api = Api(app) + # Map to ('string', 'ObjectId') passing type and format + api.add_resource(ProjectList, '/projects/') + api.add_resource(Project, '/projects/<string:project_id>') + api.add_resource(ProjectTopologies, '/projects/<string:project_id>/topologies') + api.add_resource(ProjectPortfolios, '/projects/<string:project_id>/portfolios') + api.add_resource(Topology, '/topologies/<string:topology_id>') + api.add_resource(PrefabList, '/prefabs/') + api.add_resource(Prefab, '/prefabs/<string:prefab_id>') + api.add_resource(Portfolio, '/portfolios/<string:portfolio_id>') + api.add_resource(PortfolioScenarios, '/portfolios/<string:portfolio_id>/scenarios') + api.add_resource(Scenario, '/scenarios/<string:scenario_id>') + api.add_resource(TraceList, '/traces/') + api.add_resource(Trace, '/traces/<string:trace_id>') + api.add_resource(SchedulerList, '/schedulers/') + api.add_resource(JobList, '/jobs/') + api.add_resource(Job, '/jobs/<string:job_id>') + + @app.errorhandler(AuthError) + def handle_auth_error(ex): + response = jsonify(ex.error) + response.status_code = ex.status_code + return response + + @app.errorhandler(ValidationError) + def handle_validation_error(ex): + return {'message': 'Input validation failed', 'errors': ex.messages}, 400 + + return api + + +def setup_swagger(app): + """ + Setup Swagger UI + """ + SWAGGER_URL = '/docs' + API_URL = '../schema.yml' + + swaggerui_blueprint = get_swaggerui_blueprint( + SWAGGER_URL, + API_URL, + config={ + 'app_name': "OpenDC API v2" + }, + oauth_config={ + 'clientId': os.environ.get("AUTH0_DOCS_CLIENT_ID", ""), + 'additionalQueryStringParams': {'audience': os.environ.get("AUTH0_AUDIENCE", "https://api.opendc.org/v2/")}, + } + ) + app.register_blueprint(swaggerui_blueprint) + + +def create_app(testing=False): + app = Flask(__name__, static_url_path='/') + app.config['TESTING'] = testing + app.config['SECRET_KEY'] = os.environ['OPENDC_FLASK_SECRET'] + app.config['RESTFUL_JSON'] = {'cls': JSONEncoder} + app.json_encoder = JSONEncoder + + # Define YAML content type + mimetypes.add_type('text/yaml', '.yml') + + # Setup Sentry if DSN is specified + setup_sentry() + + # Set up CORS support + CORS(app) + + # Setup compression + compress = Compress() + compress.init_app(app) + + setup_api(app) + setup_swagger(app) + + @app.route('/') + def index(): + """ + Redirect the user to the API documentation if it accesses the API root. + """ + return redirect('docs/') + + return app + + +application = create_app(testing="OPENDC_FLASK_TESTING" in os.environ) + +if __name__ == '__main__': + application.run() |
