Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: upgrade Connexion to v3 #249

Draft
wants to merge 6 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ db:
> `mySecondCollection` and `myThirdCollection`, respectively). FOCA will
> automatically register and initialize these databases and collections for you
> and add convenient clients to the app instance (accessible as children of
> `current_app.config.foca` in an [application
> `connexion.request.state.config` in an [application
> context][res-flask-app-context]). The collections would be indexed by keys
> `id`, `other_id` and `third_id`, respectively. Out of these, only `id`
> will be required to be unique.
Expand Down Expand Up @@ -443,12 +443,13 @@ my_custom_param_section:

Once the application is created using `foca()`, one can easily access any
configuration parameters from within the [application
context][res-flask-app-context] through `current_app.config.foca like so:
context][res-flask-app-context] through `connexion.request.state.config` like
so:

```python
from flask import current_app
from connexion import request

app_config = current_app.config.foca
app_config = request.state.config

db = app_config.db
api = app_config.api
Expand All @@ -457,7 +458,6 @@ exceptions = app_config.exceptions
security = app_config.security
jobs = app_config.jobs
log = app_config.log
app_specific_param = current_app.config['app_specific_param']
```

_Outside of the application context_, configuration parameters are available
Expand Down
147 changes: 147 additions & 0 deletions TESTS/proTES/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# FOCA configuration
# Available in app context as attributes of `connexion.request.state.config`
# Automatically validated via FOCA
# Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html

# Server configuration
# Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.ServerConfig
server:
host: "0.0.0.0"
port: 8080
debug: True
environment: development
testing: False
use_reloader: False

# Security configuration
# Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.SecurityConfig
security:
auth:
add_key_to_claims: True
algorithms:
- RS256
allow_expired: False
audience: null
validation_methods:
- userinfo
- public_key
validation_checks: any

# Database configuration
# Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.DBConfig
db:
host: mongodb
port: 27017
dbs:
taskStore:
collections:
tasks:
indexes:
- keys:
task_id: 1
worker_id: 1
options:
"unique": True
"sparse": True
service_info:
indexes:
- keys:
id: 1

# API configuration
# Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.APIConfig
api:
specs:
- path:
- petstore.yaml
add_operation_fields:
x-openapi-router-controller: controllers
security:
- bearerAuth: []
add_security_fields:
x-bearerInfoFunc: foca.security.auth.validate_token
disable_auth: True
connexion:
strict_validation: True
# current specs have inconsistency, therefore disabling response validation
# see: https://github.com/ga4gh/task-execution-schemas/issues/136
validate_responses: False
options:
swagger_ui: True
serve_spec: True

# Logging configuration
# Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.LogConfig
log:
version: 1
disable_existing_loggers: False
formatters:
standard:
class: logging.Formatter
style: "{"
format: "[{asctime}: {levelname:<8}] {message} [{name}]"
handlers:
console:
class: logging.StreamHandler
level: 10
formatter: standard
stream: ext://sys.stderr
root:
level: 10
handlers: [console]

jobs:
host: rabbitmq
port: 5672
backend: "rpc://"
include:
- pro_tes.tasks.track_task_progress

# Exception configuration
# Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.ExceptionConfig
exceptions:
required_members: [["message"], ["code"]]
status_member: ["code"]
exceptions: exceptions.exceptions

controllers:
post_task:
db:
insert_attempts: 10
task_id:
charset: string.ascii_uppercase + string.digits
length: 6
timeout:
post: null
poll: 2
job: null
polling:
wait: 3
attempts: 100
list_tasks:
default_page_size: 5
celery:
monitor:
timeout: 0.1
message_maxsize: 16777216

serviceInfo:
doc: Proxy TES for distributing tasks across a list of service TES instances
name: proTES
storage:
- file:///path/to/local/storage

tes:
service_list:
- "https://csc-tesk-noauth.rahtiapp.fi"
- "https://funnel.cloud.e-infra.cz/"
- "https://tesk-eu.hypatia-comp.athenarc.gr"
- "https://tesk-na.cloud.e-infra.cz"
- "https://vm4816.kaj.pouta.csc.fi/"

storeLogs:
execution_trace: True

middlewares:
- - "pro_tes.plugins.middlewares.task_distribution.distance.TaskDistributionDistance"
- "pro_tes.plugins.middlewares.task_distribution.random.TaskDistributionRandom"
10 changes: 10 additions & 0 deletions TESTS/proTES/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: '3.6'
services:

mongodb:
image: mongo:7.0
restart: unless-stopped
volumes:
- ./data/petstore/db:/data/db
ports:
- "27017:27017"
97 changes: 97 additions & 0 deletions TESTS/proTES/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""proTES exceptions."""

from connexion.exceptions import ( # type: ignore
BadRequestProblem,
ExtraParameterProblem,
Forbidden,
Unauthorized,
)
from pydantic import ValidationError
from pymongo.errors import PyMongoError # type: ignore
from werkzeug.exceptions import (
BadRequest,
InternalServerError,
NotFound,
)

# pylint: disable="too-few-public-methods"


class TaskNotFound(NotFound):
"""Raised when task with given task identifier was not found."""


class IdsUnavailableProblem(PyMongoError):
"""Raised when task identifier is unavailable."""


class NoTesInstancesAvailable(ValueError):
"""Raised when no TES instances are available."""


class MiddlewareException(ValueError):
"""Raised when a middleware could not be applied."""


class InvalidMiddleware(MiddlewareException):
"""Raised when a middleware is invalid."""


exceptions = {
Exception: {
"message": "An unexpected error occurred.",
"code": "500",
},
BadRequest: {
"message": "The request is malformed.",
"code": "400",
},
BadRequestProblem: {
"message": "The request is malformed.",
"code": "400",
},
ExtraParameterProblem: {
"message": "The request is malformed.",
"code": "400",
},
ValidationError: {
"message": "The request is malformed.",
"code": "400",
},
Unauthorized: {
"message": " The request is unauthorized.",
"code": "401",
},
Forbidden: {
"message": "The requester is not authorized to perform this action.",
"code": "403",
},
NotFound: {
"message": "The requested resource wasn't found.",
"code": "404",
},
TaskNotFound: {
"message": "The requested task wasn't found.",
"code": "404",
},
InternalServerError: {
"message": "An unexpected error occurred.",
"code": "500",
},
IdsUnavailableProblem: {
"message": "No/few unique task identifiers available.",
"code": "500",
},
NoTesInstancesAvailable: {
"message": "No valid TES instances available.",
"code": "500",
},
MiddlewareException: {
"message": "Middleware could not be applied.",
"code": "500",
},
InvalidMiddleware: {
"message": "Middleware is invalid.",
"code": "500",
},
}
Loading