Changeset View
Changeset View
Standalone View
Standalone View
swh/storage/vault/api/server.py
# Copyright (C) 2016 The Software Heritage developers | # Copyright (C) 2016 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
import click | import click | ||||
from flask import Flask, abort, g | from flask import Flask, abort, g | ||||
from werkzeug.routing import BaseConverter | |||||
from swh.core import config | from swh.core import config | ||||
from swh.objstorage.api.common import encode_data_server as encode_data | from swh.objstorage.api.common import encode_data_server as encode_data | ||||
from swh.objstorage.api.common import BytesRequest, error_handler | from swh.objstorage.api.common import BytesRequest, error_handler | ||||
from swh.storage import get_storage | from swh.storage import get_storage | ||||
from swh.storage.vault.api import cooking_tasks # NOQA | from swh.storage.vault.api import cooking_tasks # NOQA | ||||
from swh.storage.vault.cache import VaultCache | from swh.storage.vault.cache import VaultCache | ||||
from swh.storage.vault.cooker import DirectoryVaultCooker | from swh.storage.vault.cooker import DirectoryVaultCooker | ||||
from swh.scheduler.celery_backend.config import app as celery_app | from swh.scheduler.celery_backend.config import app as celery_app | ||||
from flask_profile import Profiler | |||||
cooking_task_name = 'swh.storage.vault.api.cooking_tasks.SWHCookingTask' | cooking_task_name = 'swh.storage.vault.api.cooking_tasks.SWHCookingTask' | ||||
DEFAULT_CONFIG = { | DEFAULT_CONFIG = { | ||||
'storage': ('dict', {'storage_class': 'local_storage', | 'storage': ('dict', {'storage_class': 'local_storage', | ||||
'storage_args': [ | 'storage_args': [ | ||||
'dbname=softwareheritage-dev', | 'dbname=softwareheritage-dev', | ||||
'/tmp/objects' | '/tmp/objects' | ||||
] | ] | ||||
}), | }), | ||||
'cache': ('dict', {'root': '/tmp/vaultcache'}) | 'cache': ('dict', {'root': '/tmp/vaultcache'}) | ||||
} | } | ||||
class RegexConverter(BaseConverter): | |||||
def __init__(self, url_map, *items): | |||||
super().__init__(url_map) | |||||
self.regex = items[0] | |||||
app = Flask(__name__) | app = Flask(__name__) | ||||
Profiler(app) | |||||
app.request_class = BytesRequest | app.request_class = BytesRequest | ||||
app.url_map.converters['regex'] = RegexConverter | |||||
@app.errorhandler(Exception) | @app.errorhandler(Exception) | ||||
def my_error_handler(exception): | def my_error_handler(exception): | ||||
return error_handler(exception, encode_data) | return error_handler(exception, encode_data) | ||||
@app.before_request | @app.before_request | ||||
def before_request(): | def before_request(): | ||||
g.cache = VaultCache(**app.config['cache']) | g.cache = VaultCache(**app.config['cache']) | ||||
g.cooker = DirectoryVaultCooker( | g.cooker = DirectoryVaultCooker( | ||||
get_storage(**app.config['storage']), | get_storage(**app.config['storage']), | ||||
g.cache | g.cache | ||||
) | ) | ||||
@app.route('/') | @app.route('/') | ||||
def index(): | def index(): | ||||
return 'SWH vault API server' | return 'SWH vault API server' | ||||
@app.route('/vault/directory/', methods=['GET']) | @app.route('/vault/<regex("directory|revision|snapshot"):type>/', | ||||
def ls_directory(): | methods=['GET']) | ||||
def ls_directory(type): | |||||
return encode_data(list( | return encode_data(list( | ||||
g.cache.ls('directory') | g.cache.ls(type) | ||||
)) | )) | ||||
@app.route('/vault/directory/<dir_id>/', methods=['GET']) | @app.route('/vault/<regex("directory|revision|snapshot"):type>/<id>/', | ||||
def get_cooked_directory(dir_id): | methods=['GET']) | ||||
if not g.cache.is_cached('directory', dir_id): | def get_cooked_directory(type, id): | ||||
if not g.cache.is_cached(type, id): | |||||
abort(404) | abort(404) | ||||
return encode_data(g.cache.get('directory', dir_id).decode()) | return encode_data(g.cache.get(type, id).decode()) | ||||
@app.route('/vault/directory/<dir_id>/', methods=['POST']) | @app.route('/vault/<regex("directory|revision|snapshot"):type>/<id>/', | ||||
def cook_request_directory(dir_id): | methods=['POST']) | ||||
def cook_request_directory(type, id): | |||||
task = celery_app.tasks[cooking_task_name] | task = celery_app.tasks[cooking_task_name] | ||||
task.delay(dir_id, app.config['storage'], app.config['cache']) | task.delay(type, id, app.config['storage'], app.config['cache']) | ||||
# Return url to get the content and 201 CREATED | # Return url to get the content and 201 CREATED | ||||
return encode_data('/vault/directory/dir_id/'), 201 | return encode_data('/vault/%s/%s/' % (type, id)), 201 | ||||
@click.command() | @click.command() | ||||
@click.argument('config-path', required=1) | @click.argument('config-path', required=1) | ||||
@click.option('--host', default='0.0.0.0', help="Host to run the server") | @click.option('--host', default='0.0.0.0', help="Host to run the server") | ||||
@click.option('--port', default=5000, type=click.INT, | @click.option('--port', default=5000, type=click.INT, | ||||
help="Binding port of the server") | help="Binding port of the server") | ||||
@click.option('--debug/--nodebug', default=True, | @click.option('--debug/--nodebug', default=True, | ||||
help="Indicates if the server should run in debug mode") | help="Indicates if the server should run in debug mode") | ||||
def launch(config_path, host, port, debug): | def launch(config_path, host, port, debug): | ||||
app.config.update(config.read(config_path, DEFAULT_CONFIG)) | app.config.update(config.read(config_path, DEFAULT_CONFIG)) | ||||
app.run(host, port=int(port), debug=bool(debug)) | app.run(host, port=int(port), debug=bool(debug)) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
launch() | launch() |