diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2022-04-04 17:00:31 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-04 17:00:31 +0200 |
| commit | 38769373c7e89783d33849283586bfa0b62e8251 (patch) | |
| tree | 4fda128ee6b30018c1aa14c584cc53ade80e67f7 /opendc-web/opendc-web-api/opendc/api/portfolios.py | |
| parent | 6021aa4278bebb34bf5603ead4b5daeabcdc4c19 (diff) | |
| parent | 527ae2230f5c2dd22f496f45d5d8e3bd4acdb854 (diff) | |
merge: Migrate to Quarkus-based web API
This pull request changes the web API to a Quarkus-based version. Currently, the OpenDC web API is written in Python (using Flask). Although Python is a powerful language to develop web services, having another language next to Kotlin/Java and JavaScript introduces some challenges.
For instance, the web API and UI lack integration with our Gradle-based build pipeline and require additional steps from the developer to start working with. Furthermore, deploying OpenDC requires having Python installed in addition to the JVM.
By converting the web API into a Quarkus application, we can enjoy further integration with our Gradle-based build pipeline and simplify the development/deployment process of OpenDC, by requiring only the JVM and Node to work with OpenDC.
## Implementation Notes :hammer_and_pick:
* Move build dependencies into version catalog
* Design unified communication protocol
* Add Quarkus API implementation
* Add new web client implementation
* Update runner to use new web client
* Fix compatibility with React.js UI
* Remove Python build steps from CI pipeline
* Update Docker deployment for new web API
* Remove obsolete database configuration
## External Dependencies :four_leaf_clover:
* Quarkus
## Breaking API Changes :warning:
* The new web API only supports SQL-based databases for storing user-data, as opposed to MongoDB currently. We intend to use H2 for development and Postgres for production.
Diffstat (limited to 'opendc-web/opendc-web-api/opendc/api/portfolios.py')
| -rw-r--r-- | opendc-web/opendc-web-api/opendc/api/portfolios.py | 153 |
1 files changed, 0 insertions, 153 deletions
diff --git a/opendc-web/opendc-web-api/opendc/api/portfolios.py b/opendc-web/opendc-web-api/opendc/api/portfolios.py deleted file mode 100644 index 4d8f54fd..00000000 --- a/opendc-web/opendc-web-api/opendc/api/portfolios.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright (c) 2021 AtLarge Research -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from flask import request -from flask_restful import Resource -from marshmallow import Schema, fields - -from opendc.exts import requires_auth, current_user, has_scope -from opendc.models.portfolio import Portfolio as PortfolioModel, PortfolioSchema -from opendc.models.project import Project -from opendc.models.scenario import ScenarioSchema, Scenario -from opendc.models.topology import Topology - - -class Portfolio(Resource): - """ - Resource representing a portfolio. - """ - method_decorators = [requires_auth] - - def get(self, portfolio_id): - """ - Get a portfolio by identifier. - """ - portfolio = PortfolioModel.from_id(portfolio_id) - - portfolio.check_exists() - - # Users with scope runner can access all portfolios - if not has_scope('runner'): - portfolio.check_user_access(current_user['sub'], False) - - data = PortfolioSchema().dump(portfolio.obj) - return {'data': data} - - def put(self, portfolio_id): - """ - Replace the portfolio. - """ - schema = Portfolio.PutSchema() - result = schema.load(request.json) - - portfolio = PortfolioModel.from_id(portfolio_id) - portfolio.check_exists() - portfolio.check_user_access(current_user['sub'], True) - - portfolio.set_property('name', result['portfolio']['name']) - portfolio.set_property('targets.enabledMetrics', result['portfolio']['targets']['enabledMetrics']) - portfolio.set_property('targets.repeatsPerScenario', result['portfolio']['targets']['repeatsPerScenario']) - - portfolio.update() - data = PortfolioSchema().dump(portfolio.obj) - return {'data': data} - - def delete(self, portfolio_id): - """ - Delete a portfolio. - """ - portfolio = PortfolioModel.from_id(portfolio_id) - - portfolio.check_exists() - portfolio.check_user_access(current_user['sub'], True) - - portfolio_id = portfolio.get_id() - - project = Project.from_id(portfolio.obj['projectId']) - project.check_exists() - if portfolio_id in project.obj['portfolioIds']: - project.obj['portfolioIds'].remove(portfolio_id) - project.update() - - old_object = portfolio.delete() - data = PortfolioSchema().dump(old_object) - return {'data': data} - - class PutSchema(Schema): - """ - Schema for the PUT operation on a portfolio. - """ - portfolio = fields.Nested(PortfolioSchema, required=True) - - -class PortfolioScenarios(Resource): - """ - Resource representing the scenarios of a portfolio. - """ - method_decorators = [requires_auth] - - def get(self, portfolio_id): - """ - Get all scenarios belonging to a portfolio. - """ - portfolio = PortfolioModel.from_id(portfolio_id) - - portfolio.check_exists() - portfolio.check_user_access(current_user['sub'], True) - - scenarios = Scenario.get_for_portfolio(portfolio_id) - - data = ScenarioSchema().dump(scenarios, many=True) - return {'data': data} - - def post(self, portfolio_id): - """ - Add a new scenario to this portfolio - """ - schema = PortfolioScenarios.PostSchema() - result = schema.load(request.json) - - portfolio = PortfolioModel.from_id(portfolio_id) - - portfolio.check_exists() - portfolio.check_user_access(current_user['sub'], True) - - scenario = Scenario(result['scenario']) - - topology = Topology.from_id(scenario.obj['topology']['topologyId']) - topology.check_exists() - topology.check_user_access(current_user['sub'], True) - - scenario.set_property('portfolioId', portfolio.get_id()) - scenario.set_property('simulation', {'state': 'QUEUED'}) - scenario.set_property('topology.topologyId', topology.get_id()) - - scenario.insert() - - portfolio.obj['scenarioIds'].append(scenario.get_id()) - portfolio.update() - data = ScenarioSchema().dump(scenario.obj) - return {'data': data} - - class PostSchema(Schema): - """ - Schema for the POST operation on a portfolio's scenarios. - """ - scenario = fields.Nested(ScenarioSchema, required=True) |
