diff --git a/messages/v1/messages/applicationservice.create.yml b/messages/v1/messages/applicationservice.create.yml index 295a651..085b6d6 100644 --- a/messages/v1/messages/applicationservice.create.yml +++ b/messages/v1/messages/applicationservice.create.yml @@ -19,6 +19,11 @@ parameters: shortarg: d description: | Description du service applicatif à créer. + applicationservice_dependencies: + type: '[]Number' + shortarg: a + description: ID des services applicatif donc dépendant le service applicatif. + default: [] release_id: type: Number shortarg: r @@ -28,19 +33,3 @@ parameters: response: type: ApplicationService description: Informations sur le service applicatif créé. - -errors: - - uri: servermodel.create.error.database_not_available - - uri: servermodel.create.error.duplicate_servermodel - - uri: servermodel.create.error.invalid_parentservermodel_id - - uri: servermodel.create.error.invalid_source_id - - uri: servermodel.create.error.unknown_parentservermodel_id - - uri: servermodel.create.error.unknown_source_id - - uri: servermodel.create.error.servermodelname_not_provided - -related: - - servermodel.list - - servermodel.describe - - servermodel.update - - servermodel.delete - - servermodel.event diff --git a/messages/v1/messages/applicationservice.describe.yml b/messages/v1/messages/applicationservice.describe.yml new file mode 100644 index 0000000..8e6c4a5 --- /dev/null +++ b/messages/v1/messages/applicationservice.describe.yml @@ -0,0 +1,25 @@ +--- +uri: applicationservice.describe + +description: | + Décrit un service applicatif. + +pattern: rpc + +public: true + +parameters: + applicationservice_name: + type: String + shortarg: n + description: | + Nom du service applicatif à créer. + release_id: + type: Number + shortarg: r + description: | + Identifiant de la version associée au service applicatif. + +response: + type: ApplicationService + description: Informations sur le service applicatif. diff --git a/src/risotto/config.py b/src/risotto/config.py index 81fc16a..36ef8b2 100644 --- a/src/risotto/config.py +++ b/src/risotto/config.py @@ -1,6 +1,5 @@ HTTP_PORT = 8080 MESSAGE_ROOT_PATH = 'messages' -ROOT_CACHE_DIR = 'cache' DEBUG = True DATABASE_DIR = 'database' INTERNAL_USER = 'internal' diff --git a/src/risotto/dispatcher.py b/src/risotto/dispatcher.py index e966fab..e32ba2a 100644 --- a/src/risotto/dispatcher.py +++ b/src/risotto/dispatcher.py @@ -2,6 +2,7 @@ from tiramisu import Config from traceback import print_exc from copy import copy from typing import Dict, Callable +from json import dumps, loads from .utils import _ from .error import CallError, NotAllowedError @@ -104,6 +105,12 @@ class CallDispatcher: db_conf = get_config().get('database') pool = await asyncpg.create_pool(database=db_conf.get('dbname'), user=db_conf.get('user')) async with pool.acquire() as connection: + await connection.set_type_codec( + 'json', + encoder=dumps, + decoder=loads, + schema='pg_catalog' + ) risotto_context.connection = connection async with connection.transaction(): returns = await risotto_context.function(self.injected_self[function_obj['module']], **kw) @@ -177,10 +184,18 @@ class PublishDispatcher: if function_obj['risotto_context']: kw['risotto_context'] = risotto_context # send event - if function_obj['database']: + if function_obj['database'] and hasattr(old_risotto_context, 'connection'): + risotto_context.connection = old_risotto_context.connection + if function_obj['database'] and not hasattr(risotto_context, 'connection'): db_conf = get_config().get('database') pool = await asyncpg.create_pool(database=db_conf.get('dbname'), user=db_conf.get('user')) async with pool.acquire() as connection: + await connection.set_type_codec( + 'json', + encoder=dumps, + decoder=loads, + schema='pg_catalog' + ) risotto_context.connection = connection async with connection.transaction(): returns = await function(self.injected_self[function_obj['module']], **kw) diff --git a/src/risotto/logger.py b/src/risotto/logger.py index b8f1655..aefb61d 100644 --- a/src/risotto/logger.py +++ b/src/risotto/logger.py @@ -53,5 +53,10 @@ class Logger: if DEBUG: print(tmsg) + def info(self, + msg): + if DEBUG: + print(msg) + log = Logger() diff --git a/src/risotto/services/applicationservice/applicationservice.py b/src/risotto/services/applicationservice/applicationservice.py index ebc632f..9d6ad1e 100644 --- a/src/risotto/services/applicationservice/applicationservice.py +++ b/src/risotto/services/applicationservice/applicationservice.py @@ -2,7 +2,7 @@ from os import listdir from os.path import join from traceback import print_exc from yaml import load, SafeLoader -from typing import Dict +from typing import Dict, List from ...controller import Controller from ...register import register @@ -19,13 +19,15 @@ class Risotto(Controller): risotto_context: Context, applicationservice_name: str, applicationservice_description: str, + applicationservice_dependencies: List[int], release_id: int) -> Dict: - applicationservice_update_query = """INSERT INTO ApplicationService(ApplicationServiceName, ApplicationServiceDescription, ApplicationServiceReleaseId) VALUES ($1,$2,$3) + applicationservice_update_query = """INSERT INTO ApplicationService(ApplicationServiceName, ApplicationServiceDescription, ApplicationServiceDependencies, ApplicationServiceReleaseId) VALUES ($1,$2,$3,$4) RETURNING ApplicationServiceId """ applicationservice_id = await risotto_context.connection.fetchval(applicationservice_update_query, applicationservice_name, applicationservice_description, + applicationservice_dependencies, release_id) return {'applicationservice_name': applicationservice_name, 'applicationservice_description': applicationservice_description, @@ -37,10 +39,12 @@ class Risotto(Controller): risotto_context: Context, applicationservice_name: str, applicationservice_description: str, + applicationservice_dependencies: List[int], release_id: int) -> Dict: return await self._applicationservice_create(risotto_context, applicationservice_name, applicationservice_description, + applicationservice_dependencies, release_id) @register('v1.applicationservice.dataset.updated', None, database=True) @@ -76,6 +80,7 @@ class Risotto(Controller): await self._applicationservice_create(risotto_context, applicationservice_description['name'], applicationservice_description['description'], + [], # FIXME dependencies release_id) except Exception as err: if get_config().get('global').get('debug'): @@ -96,7 +101,20 @@ class Risotto(Controller): applicationservice_id) if applicationservice is None: raise Exception(_(f'unknown service with ID {applicationservice_id}')) - applicationservice = dict(applicationservice) - if applicationservice['applicationservice_dependencies'] is None: - applicationservice['applicationservice_dependencies'] = [] - return applicationservice + return dict(applicationservice) + + @register('v1.applicationservice.describe', None, database=True) + async def applicationservice_describe(self, + risotto_context: Context, + applicationservice_name, + release_id): + applicationservice_query = """ + SELECT ApplicationServiceId as applicationservice_id, ApplicationServiceName as applicationservice_name, ApplicationServiceDependencies as applicationservice_dependencies, ApplicationServiceReleaseId as applicationservice_release_id + FROM ApplicationService + WHERE ApplicationServiceName=$1 AND ApplicationServiceReleaseId=$2""" + applicationservice = await risotto_context.connection.fetchrow(applicationservice_query, + applicationservice_name, + release_id) + if applicationservice is None: + raise Exception(_(f'unknown service {applicationservice_name} in release ID {release_id}')) + return dict(applicationservice) diff --git a/src/risotto/services/config/config.py b/src/risotto/services/config/config.py index 82b7087..072d9c4 100644 --- a/src/risotto/services/config/config.py +++ b/src/risotto/services/config/config.py @@ -10,7 +10,7 @@ from rougail import load as rougail_load from ...controller import Controller from ...register import register -from ...config import ROOT_CACHE_DIR, DATABASE_DIR, DEBUG, ROUGAIL_DTD_PATH +from ...config import DATABASE_DIR, DEBUG, ROUGAIL_DTD_PATH, get_config from ...context import Context from ...utils import _ from ...error import CallError, RegistrationError @@ -20,7 +20,8 @@ from ...logger import log class Risotto(Controller): def __init__(self) -> None: - for dirname in [ROOT_CACHE_DIR, DATABASE_DIR]: + self.cache_root_path = join(get_config().get('cache').get('root_path'), 'servermodel') + for dirname in [self.cache_root_path, DATABASE_DIR]: if not isdir(dirname): raise RegistrationError(_(f'unable to find the cache dir "{dirname}"')) self.save_storage = Storage(engine='sqlite3', dir_database=DATABASE_DIR) @@ -65,7 +66,7 @@ class Risotto(Controller): def get_funcs_filename(self, servermodel_id: int): - return join(ROOT_CACHE_DIR, str(servermodel_id)+".creolefuncs") + return join(self.cache_root_path, str(servermodel_id)+".creolefuncs") @@ -75,7 +76,7 @@ class Risotto(Controller): servermodel_name: str) -> None: """ Loads a servermodel """ - cache_file = join(ROOT_CACHE_DIR, str(servermodel_id)+".xml") + cache_file = join(self.cache_root_path, str(servermodel_id)+".xml") funcs_file = self.get_funcs_filename(servermodel_id) log.info_msg(risotto_context, None, @@ -353,7 +354,7 @@ class Risotto(Controller): None, f'Reload servermodel {servermodel_name} ({servermodel_id})') # unlink cache to force download new aggregated file - cache_file = join(ROOT_CACHE_DIR, str(servermodel_id)+".xml") + cache_file = join(self.cache_root_path, str(servermodel_id)+".xml") if isfile(cache_file): unlink(cache_file) diff --git a/src/risotto/services/servermodel/servermodel.py b/src/risotto/services/servermodel/servermodel.py index ef6c1f5..8053cbd 100644 --- a/src/risotto/services/servermodel/servermodel.py +++ b/src/risotto/services/servermodel/servermodel.py @@ -11,6 +11,7 @@ from ...utils import _ from ...context import Context from ...config import get_config from ...error import ExecutionError +from ...logger import log class Risotto(Controller): @@ -35,6 +36,7 @@ class Risotto(Controller): async def servermodel_gen_schema(self, risotto_context: Context, + servermodel_name: str, servermodel_id: int, applicationservice_id: int, release_cache: Dict) -> None: @@ -43,8 +45,10 @@ class Risotto(Controller): if release_cache is None: release_cache = {} dict_paths = [] + as_names = [] for applicationservice_id, applicationservice_infos in dependencies.items(): applicationservice_name, as_release_id = applicationservice_infos + as_names.append(applicationservice_name) if as_release_id not in release_cache: release_cache[as_release_id] = await self.call('v1.source.release.get_by_id', risotto_context, @@ -56,6 +60,8 @@ class Risotto(Controller): applicationservice_name, 'dictionaries')) eolobj = CreoleObjSpace(dtdfilename) + as_names_str = '", "'.join(as_names) + log.info(_(f'gen schema for "{servermodel_name}" with application services "{as_names_str}"')) eolobj.create_or_populate_from_xml('creole', dict_paths) # FIXME extra # FIXME eosfunc @@ -68,6 +74,7 @@ class Risotto(Controller): servermodel_name: str, servermodel_description: str, servermodel_parents_id: List[int], + dependencies: List[int], release_id: int, release_cache: Dict=None) -> Dict: servermodel_update = """INSERT INTO Servermodel(ServermodelName, ServermodelDescription, ServermodelParentsId, ServermodelReleaseId, ServermodelApplicationServiceId) @@ -80,6 +87,7 @@ class Risotto(Controller): risotto_context, applicationservice_name=as_name, applicationservice_description=as_description, + applicationservice_dependencies=dependencies, release_id=self.internal_release_id) applicationservice_id = applicationservice['applicationservice_id'] servermodel_id = await risotto_context.connection.fetchval(servermodel_update, @@ -89,6 +97,7 @@ class Risotto(Controller): release_id, applicationservice_id) await self.servermodel_gen_schema(risotto_context, + servermodel_name, servermodel_id, applicationservice_id, release_cache) @@ -169,6 +178,14 @@ class Risotto(Controller): servermodelparent_id = [await self.get_servermodel_id_by_name(risotto_context, parent, release_id)] + # link application service with this servermodel + dependencies = [] + for depend in servermodels[new_servermodel]['applicationservices']: + applicationservice = await self.call('v1.applicationservice.describe', + risotto_context, + applicationservice_name=depend, + release_id=release_id) + dependencies.append(applicationservice['applicationservice_id']) sm_name = servermodel_description['name'] sm_description = servermodel_description['description'] try: @@ -176,6 +193,7 @@ class Risotto(Controller): sm_name, sm_description, servermodelparent_id, + dependencies, release_id, release_cache) servermodel_id = servermodel_ob['servermodel_id'] diff --git a/src/risotto/services/template/template.py b/src/risotto/services/template/template.py index 02aadda..41cae22 100644 --- a/src/risotto/services/template/template.py +++ b/src/risotto/services/template/template.py @@ -3,7 +3,7 @@ from os.path import isdir, join from shutil import rmtree from rougail.template import generate from tiramisu import Storage -from ...config import ROOT_CACHE_DIR, CONFIGURATION_DIR, TEMPLATE_DIR, TMP_DIR +from ...config import CONFIGURATION_DIR, TEMPLATE_DIR, TMP_DIR from ...controller import Controller from ...register import register from ...dispatcher import dispatcher