#!/usr/bin/env python3 import os from dotenv import load_dotenv from flask import Flask, jsonify from flask_compress import Compress from flask_cors import CORS from flask_restful import Api from marshmallow import ValidationError 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/') api.add_resource(ProjectTopologies, '/projects//topologies') api.add_resource(ProjectPortfolios, '/projects//portfolios') api.add_resource(Topology, '/topologies/') api.add_resource(PrefabList, '/prefabs/') api.add_resource(Prefab, '/prefabs/') api.add_resource(Portfolio, '/portfolios/') api.add_resource(PortfolioScenarios, '/portfolios//scenarios') api.add_resource(Scenario, '/scenarios/') api.add_resource(TraceList, '/traces/') api.add_resource(Trace, '/traces/') api.add_resource(SchedulerList, '/schedulers/') @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 create_app(testing=False): app = Flask(__name__) app.config['TESTING'] = testing app.config['SECRET_KEY'] = os.environ['OPENDC_FLASK_SECRET'] app.config['RESTFUL_JSON'] = {'cls': JSONEncoder} app.json_encoder = JSONEncoder # Setup Sentry if DSN is specified setup_sentry() # Set up CORS support CORS(app) # Setup compression compress = Compress() compress.init_app(app) # Setup API setup_api(app) return app application = create_app(testing="OPENDC_FLASK_TESTING" in os.environ) if __name__ == '__main__': application.run()