server>template

This commit is contained in:
Emmanuel Garette 2019-12-20 10:58:12 +01:00
parent 6b8a88e103
commit 4de9bde691
9 changed files with 171 additions and 144 deletions

View File

@ -1,49 +0,0 @@
---
uri: server.describe
description: |
Retourne les attributs détaillés dun serveur.
sampleuse: |
zephir-client server.describe -s 1
pattern: rpc
public: true
domain: server-domain
parameters:
serverid:
type: Number
ref: Server.ServerId
description: Identifiant du serveur.
shortarg: s
configuration:
type: Boolean
description: Inclure les valeurs de configuration.
default: false
environment:
type: Boolean
description: Inclure les variables d'environement.
default: false
peering:
type: Boolean
description: Inclure la clé d'appairage.
default: false
response:
type: ServerDescribe
description: Description du serveur.
errors:
- uri: server.error.database-not-available
- uri: server.error.db-connection
- uri: server.error.invalid-server-id
- uri: server.error.unknown-server-id
related:
- server.list
- server.create
- server.update
- server.delete

View File

@ -0,0 +1,18 @@
---
uri: server.describe
description: Retourne les attributs détaillés dun serveur.
pattern: rpc
public: true
parameters:
server_name:
type: String
ref: Server.ServerName
description: Nom du serveur.
response:
type: Server
description: Description du serveur.

View File

@ -9,12 +9,12 @@ pattern: rpc
public: true public: true
parameters: parameters:
server_id: server_name:
type: Number type: String
ref: Server.ServerId ref: Server.ServerName
shortarg: s shortarg: s
description: | description: |
Identifiant du serveur. Nom du serveur.
response: response:
type: Template type: Template

View File

@ -1,44 +0,0 @@
---
title: ServerDescribe
type: object
description: Description du serveur.
properties:
serverid:
type: number
description: Identifiant du serveur.
ref: Server.ServerId
servername:
type: string
description: Nom du serveur.
serverdescription:
type: string
description: Description du serveur.
servermodelid:
type: number
description: Identifiant du modèle de serveur.
ref: Servermodel.ServermodelId
zoneid:
type: number
description: Identifiant de la zone.
ref: Zone.ZoneId
machineid:
type: number
description: Identifiant de la machine.
ref: Zone.MachineId
configuration:
type: file
description: Valeurs de configuration.
serverenvironment:
type: object
description: Variables d'environnement du serveur.
peering:
type: object
description: Clé d'appairage.
lastpeerconnection:
type: string
description: Timestamp de la dernière connexion avec le serveur.
required:
- serverid
- servername
- serverdescription
- servermodelid

View File

@ -47,7 +47,7 @@ CREATE TABLE ApplicationService (
-- Server table creation -- Server table creation
CREATE TABLE Server ( CREATE TABLE Server (
ServerId SERIAL PRIMARY KEY, ServerId SERIAL PRIMARY KEY,
ServerName VARCHAR(255) NOT NULL, ServerName VARCHAR(255) NOT NULL UNIQUE,
ServerDescription VARCHAR(255) NOT NULL, ServerDescription VARCHAR(255) NOT NULL,
ServerServermodelId INTEGER NOT NULL ServerServermodelId INTEGER NOT NULL
); );

View File

@ -66,9 +66,7 @@ class Risotto(Controller):
def get_funcs_filename(self, def get_funcs_filename(self,
servermodel_id: int): servermodel_id: int):
return join(self.cache_root_path, str(servermodel_id)+".creolefuncs") return join(self.cache_root_path, str(servermodel_id), "funcs.py")
async def load_servermodel(self, async def load_servermodel(self,
risotto_context: Context, risotto_context: Context,
@ -76,7 +74,7 @@ class Risotto(Controller):
servermodel_name: str) -> None: servermodel_name: str) -> None:
""" Loads a servermodel """ Loads a servermodel
""" """
cache_file = join(self.cache_root_path, str(servermodel_id)+".xml") cache_file = join(self.cache_root_path, str(servermodel_id), "dictionaries.xml")
funcs_file = self.get_funcs_filename(servermodel_id) funcs_file = self.get_funcs_filename(servermodel_id)
log.info_msg(risotto_context, log.info_msg(risotto_context,
None, None,

View File

@ -3,6 +3,7 @@ from typing import Dict
from ...controller import Controller from ...controller import Controller
from ...register import register from ...register import register
from ...context import Context from ...context import Context
from ...utils import _
class Risotto(Controller): class Risotto(Controller):
@ -10,7 +11,8 @@ class Risotto(Controller):
async def server_list(self, async def server_list(self,
risotto_context: Context) -> Dict: risotto_context: Context) -> Dict:
sql = ''' sql = '''
SELECT ServerId as server_id, ServerName as server_name, ServerDescription as server_description, ServerServermodelId as server_servermodel_id FROM Server SELECT ServerId as server_id, ServerName as server_name, ServerDescription as server_description, ServerServermodelId as server_servermodel_id
FROM Server
''' '''
servers = await risotto_context.connection.fetch(sql) servers = await risotto_context.connection.fetch(sql)
return [dict(r) for r in servers] return [dict(r) for r in servers]
@ -18,9 +20,9 @@ class Risotto(Controller):
@register('v1.server.create', 'v1.server.created', database=True) @register('v1.server.create', 'v1.server.created', database=True)
async def server_create(self, async def server_create(self,
risotto_context: Context, risotto_context: Context,
server_name, server_name: str,
server_description, server_description: str,
server_servermodel_id) -> Dict: server_servermodel_id: int) -> Dict:
await self.call('v1.servermodel.get_by_id', await self.call('v1.servermodel.get_by_id',
risotto_context, risotto_context,
@ -37,3 +39,18 @@ class Risotto(Controller):
'server_name': server_name, 'server_name': server_name,
'server_description': server_description, 'server_description': server_description,
'server_servermodel_id': server_servermodel_id} 'server_servermodel_id': server_servermodel_id}
@register('v1.server.describe', None, database=True)
async def server_create(self,
risotto_context: Context,
server_name: str) -> Dict:
sql = '''
SELECT ServerId as server_id, ServerName as server_name, ServerDescription as server_description, ServerServermodelId as server_servermodel_id
FROM Server
WHERE ServerName = $1
'''
server = await risotto_context.connection.fetchrow(sql,
server_name)
if not server:
raise Exception(_(f'unable to find server with name {server_name}'))
return dict(server)

View File

@ -1,8 +1,9 @@
from shutil import rmtree, copyfile
from os import listdir, makedirs from os import listdir, makedirs
from os.path import join, isdir from os.path import join, isdir, isfile
from yaml import load, SafeLoader from yaml import load, SafeLoader
from traceback import print_exc from traceback import print_exc
from typing import Dict, List from typing import Dict, List, Optional
from rougail import CreoleObjSpace from rougail import CreoleObjSpace
from rougail.config import dtdfilename from rougail.config import dtdfilename
from ...controller import Controller from ...controller import Controller
@ -34,40 +35,94 @@ class Risotto(Controller):
release_distribution='stable') release_distribution='stable')
self.internal_release_id = internal_release['release_id'] self.internal_release_id = internal_release['release_id']
async def servermodel_gen_schema(self, def servermodel_gen_funcs(self,
risotto_context: Context, servermodel_name: str,
servermodel_name: str, servermodel_id: int,
servermodel_id: int, dependencies: Dict,
applicationservice_id: int, release_cache: Dict) -> None:
release_cache: Dict) -> None: as_names = []
dependencies = await self.get_applicationservices(risotto_context, dest_file = self.get_servermodel_cache(servermodel_id, 'funcs.py')
applicationservice_id) with open(dest_file, 'w') as funcs:
if release_cache is None: for applicationservice_id, applicationservice_infos in dependencies.items():
release_cache = {} applicationservice_name, as_release_id = applicationservice_infos
dict_paths = [] path = join(self.source_root_path,
release_cache[as_release_id]['source_name'],
release_cache[as_release_id]['release_name'],
'applicationservice',
applicationservice_name,
'funcs')
if isdir(path):
as_names.append(applicationservice_name)
for fil in listdir(path):
with open(join(path, fil), 'r') as fh:
funcs.write('# {}\n'.format(join(path, fil)))
funcs.write(fh.read() + '\n')
as_names_str = '", "'.join(as_names)
log.info(_(f'gen funcs for "{servermodel_name}" with application services "{as_names_str}"'))
eolobj = CreoleObjSpace(dtdfilename)
def servermodel_gen_schema(self,
servermodel_name: str,
servermodel_id: int,
dependencies: Dict,
release_cache: Dict) -> None:
paths = []
as_names = [] as_names = []
for applicationservice_id, applicationservice_infos in dependencies.items(): for applicationservice_id, applicationservice_infos in dependencies.items():
applicationservice_name, as_release_id = applicationservice_infos applicationservice_name, as_release_id = applicationservice_infos
as_names.append(applicationservice_name) path = join(self.source_root_path,
if as_release_id not in release_cache: release_cache[as_release_id]['source_name'],
release_cache[as_release_id] = await self.call('v1.source.release.get_by_id', release_cache[as_release_id]['release_name'],
risotto_context, 'applicationservice',
release_id=as_release_id) applicationservice_name,
dict_paths.append(join(self.source_root_path, 'dictionaries')
release_cache[as_release_id]['source_name'], if isdir(path):
release_cache[as_release_id]['release_name'], as_names.append(applicationservice_name)
'applicationservice', paths.append(path)
applicationservice_name,
'dictionaries'))
eolobj = CreoleObjSpace(dtdfilename) eolobj = CreoleObjSpace(dtdfilename)
as_names_str = '", "'.join(as_names) as_names_str = '", "'.join(as_names)
log.info(_(f'gen schema for "{servermodel_name}" with application services "{as_names_str}"')) log.info(_(f'gen schema for "{servermodel_name}" with application services "{as_names_str}"'))
eolobj.create_or_populate_from_xml('creole', dict_paths) eolobj.create_or_populate_from_xml('creole', paths)
# FIXME extra # FIXME extra
# FIXME eosfunc funcs_file = self.get_servermodel_cache(servermodel_id, 'funcs.py')
eosfunc = '/eosfunc.py' eolobj.space_visitor(funcs_file)
eolobj.space_visitor(eosfunc) dest_dir = self.get_servermodel_cache(servermodel_id, 'dictionaries.xml')
eolobj.save(join(self.cache_root_path, f'{servermodel_id}.xml')) eolobj.save(dest_dir)
def get_servermodel_cache(self,
servermodel_id: int,
subdir: Optional[str]=None) -> str:
if subdir:
return join(self.cache_root_path, str(servermodel_id), subdir)
return join(self.cache_root_path, str(servermodel_id))
def servermodel_copy_templates(self,
servermodel_name: str,
servermodel_id: int,
dependencies: Dict,
release_cache: Dict) -> None:
as_names = []
dest_dir = self.get_servermodel_cache(servermodel_id, 'templates')
makedirs(dest_dir)
for applicationservice_id, applicationservice_infos in dependencies.items():
applicationservice_name, as_release_id = applicationservice_infos
path = join(self.source_root_path,
release_cache[as_release_id]['source_name'],
release_cache[as_release_id]['release_name'],
'applicationservice',
applicationservice_name,
'templates')
if isdir(path):
for template in listdir(path):
template_path = join(dest_dir, template)
if isfile(template_path):
as_names_str = '", "'.join(as_names)
raise Exception(_(f'duplicate "{template}" when copying template from "{applicationservice_name}" to "{dest_dir}" for servermodel "{servermodel_name}" (previous application services was "{as_names_str}"'))
copyfile(join(path, template), template_path)
as_names.append(applicationservice_name)
as_names_str = '", "'.join(as_names)
log.info(_(f'copy templates for "{servermodel_name}" with application services "{as_names_str}"'))
async def _servermodel_create(self, async def _servermodel_create(self,
risotto_context: Context, risotto_context: Context,
@ -96,11 +151,35 @@ class Risotto(Controller):
servermodel_parents_id, servermodel_parents_id,
release_id, release_id,
applicationservice_id) applicationservice_id)
await self.servermodel_gen_schema(risotto_context, dest_dir = self.get_servermodel_cache(servermodel_id)
servermodel_name, if isdir(dest_dir):
servermodel_id, rmtree(dest_dir)
applicationservice_id, makedirs(dest_dir)
release_cache) # get all dependencies for this application service
dependencies = await self.get_applicationservices(risotto_context,
applicationservice_id)
# build cache to have all release informations
if release_cache is None:
release_cache = {}
for applicationservice_id, applicationservice_infos in dependencies.items():
applicationservice_name, as_release_id = applicationservice_infos
if as_release_id not in release_cache:
release_cache[as_release_id] = await self.call('v1.source.release.get_by_id',
risotto_context,
release_id=as_release_id)
self.servermodel_gen_funcs(servermodel_name,
servermodel_id,
dependencies,
release_cache)
self.servermodel_gen_schema(servermodel_name,
servermodel_id,
dependencies,
release_cache)
self.servermodel_copy_templates(servermodel_name,
servermodel_id,
dependencies,
release_cache)
sm_dict = {'servermodel_name': servermodel_name, sm_dict = {'servermodel_name': servermodel_name,
'servermodel_description': servermodel_description, 'servermodel_description': servermodel_description,
'servermodel_parents_id': servermodel_parents_id, 'servermodel_parents_id': servermodel_parents_id,

View File

@ -1,21 +1,30 @@
from os import mkdir from os import mkdir
from os.path import isdir, join from os.path import isdir, join
from shutil import rmtree from shutil import rmtree
from typing import Dict
from rougail.template import generate from rougail.template import generate
from tiramisu import Storage from tiramisu import Storage
from ...config import CONFIGURATION_DIR, TEMPLATE_DIR, TMP_DIR from ...config import CONFIGURATION_DIR, TMP_DIR, get_config
from ...controller import Controller from ...controller import Controller
from ...register import register from ...register import register
from ...dispatcher import dispatcher from ...dispatcher import dispatcher
from ...utils import _
class Risotto(Controller): class Risotto(Controller):
def __init__(self): def __init__(self):
self.storage = Storage(engine='dictionary') self.storage = Storage(engine='dictionary')
self.cache_root_path = join(get_config().get('cache').get('root_path'), 'servermodel')
@register('v1.template.generate', None) @register('v1.template.generate', None)
async def template_get(self, async def template_get(self,
server_id: int): risotto_context,
server_name: str) -> Dict:
server = await self.call('v1.server.describe',
risotto_context,
server_name=server_name)
server_id = server['server_id']
servermodel_id = server['server_servermodel_id']
config_module = dispatcher.get_service('config') config_module = dispatcher.get_service('config')
server = config_module.server[server_id] server = config_module.server[server_id]
config = meta = server['server'].config.deepcopy(storage=self.storage) config = meta = server['server'].config.deepcopy(storage=self.storage)
@ -28,7 +37,6 @@ class Risotto(Controller):
config = children[0] config = children[0]
else: else:
break break
print(config.value.dict())
configurations_dir = join(CONFIGURATION_DIR, configurations_dir = join(CONFIGURATION_DIR,
str(server_id)) str(server_id))
if isdir(configurations_dir): if isdir(configurations_dir):
@ -38,7 +46,7 @@ class Risotto(Controller):
if isdir(tmp_dir): if isdir(tmp_dir):
rmtree(tmp_dir) rmtree(tmp_dir)
mkdir(tmp_dir) mkdir(tmp_dir)
templates_dir = join(TEMPLATE_DIR, str(server_id)) templates_dir = join(self.cache_root_path, str(servermodel_id), 'templates')
generate(config, generate(config,
server['funcs_file'], server['funcs_file'],
templates_dir, templates_dir,